├── .gitignore ├── README.md ├── SDL2.dll ├── pi3d ├── .gitignore ├── Cargo.toml ├── build.rs ├── examples │ ├── cities │ │ ├── cities150.txt │ │ ├── cities200.txt │ │ ├── cities30.txt │ │ ├── cities50.txt │ │ └── cities80.txt │ ├── ecubes │ │ ├── License.txt │ │ ├── README.TXT │ │ ├── miramar_256_back.png │ │ ├── miramar_256_bottom.png │ │ ├── miramar_256_front.png │ │ ├── miramar_256_left.png │ │ ├── miramar_256_right.png │ │ ├── miramar_256_top.png │ │ ├── sbox_back.jpg │ │ ├── sbox_bottom.jpg │ │ ├── sbox_front.jpg │ │ ├── sbox_left.jpg │ │ ├── sbox_right.jpg │ │ └── sbox_top.jpg │ ├── farris.rs │ ├── fonts │ │ ├── NotoSans-Regular.ttf │ │ ├── NotoSerif-Regular.ttf │ │ └── Str437.ttf │ ├── forest_walk.rs │ ├── game.rs │ ├── minimal.rs │ ├── models │ │ ├── CargoHoldBaked2.mtl │ │ ├── CargoHoldBaked2.obj │ │ ├── CargoHold_CollisionBig.obj │ │ ├── Raspi256x256.png │ │ ├── biplane.mtl │ │ ├── biplane.obj │ │ ├── biplane1.jpg │ │ ├── earthskybox.mtl │ │ ├── earthskybox.obj │ │ ├── iss.mtl │ │ ├── iss.obj │ │ ├── leeds_raspberry_jam02c.png │ │ ├── maps │ │ │ ├── ChevronsCompleteMap.jpg │ │ │ ├── MedMon1.png │ │ │ ├── ashphalt.jpg │ │ │ ├── barriersCompleteMap.jpg │ │ │ ├── bluealum.jpg │ │ │ ├── bluealumCompleteMap.jpg │ │ │ ├── blueglow.png │ │ │ ├── bodyCompleteMap.jpg │ │ │ ├── fx3_Panels.png │ │ │ ├── panelCompleteMap.png │ │ │ ├── radar.png │ │ │ ├── red.png │ │ │ ├── rodsCompleteMap.png │ │ │ ├── sbox_512_back.png │ │ │ ├── sbox_512_bottom.png │ │ │ ├── sbox_512_front.png │ │ │ ├── sbox_512_left.png │ │ │ ├── sbox_512_right.png │ │ │ ├── sbox_512_top.png │ │ │ ├── stripsCompleteMap.jpg │ │ │ ├── walkplate.png │ │ │ ├── walkwaysCompleteMap.jpg │ │ │ └── white.png │ │ ├── pi3d.mtl │ │ ├── pi3d.obj │ │ ├── pi3d_old.mtl │ │ ├── pi3d_old.obj │ │ ├── rust_pi3d.mtl │ │ ├── rust_pi3d.obj │ │ └── sphere.obj │ ├── picture_frame.rs │ ├── shader_in_src.rs │ ├── shaders │ │ ├── blend_new.fs │ │ ├── blend_new.vs │ │ ├── farris_p67.fs │ │ ├── farris_p67.vs │ │ ├── farris_p67a.fs │ │ ├── farris_p67a.vs │ │ ├── farris_p67b.fs │ │ ├── farris_p67b.vs │ │ ├── farris_p67b_ES30.fs │ │ ├── farris_p67b_ES30.vs │ │ ├── farris_p6_6term.fs │ │ ├── farris_p6_6term.vs │ │ ├── triangle.fs │ │ ├── triangle.vs │ │ ├── uv_flat_ES30.fs │ │ ├── uv_flat_ES30.vs │ │ ├── uv_light.fs │ │ ├── uv_light.vs │ │ ├── uv_pointsprite_ES30.fs │ │ └── uv_pointsprite_ES30.vs │ ├── ship_demo.rs │ ├── textures │ │ ├── floor_nm.jpg │ │ ├── grasstile_n.jpg │ │ ├── hornbeam2.png │ │ ├── mountains3_512.jpg │ │ ├── mountainsHgt.png │ │ ├── pattern.png │ │ ├── poppy1.jpg │ │ ├── stars.jpg │ │ ├── tree1.png │ │ └── tree2.png │ └── tsp.rs └── src │ ├── buffer.rs │ ├── camera.rs │ ├── display.rs │ ├── lib.rs │ ├── light.rs │ ├── shader.rs │ ├── shaders │ ├── built_in_shaders.rs │ └── mod.rs │ ├── shape.rs │ ├── shapes │ ├── cone.rs │ ├── cuboid.rs │ ├── cylinder.rs │ ├── elevation_map.rs │ ├── environment_cube.rs │ ├── lathe.rs │ ├── lines.rs │ ├── merge_shape.rs │ ├── mod.rs │ ├── model_obj.rs │ ├── plane.rs │ ├── point_text.rs │ ├── points.rs │ ├── sphere.rs │ ├── string.rs │ ├── tcone.rs │ ├── torus.rs │ └── tube.rs │ ├── texture.rs │ └── util │ ├── font.rs │ ├── mod.rs │ ├── offscreen_texture.rs │ ├── post_process.rs │ ├── resources.rs │ ├── vec3.rs │ └── vec4.rs ├── pyo3_module ├── Cargo.lock ├── Cargo.toml ├── README.md ├── setup.py ├── src │ ├── core.rs │ ├── lib.rs │ ├── shapes.rs │ └── util.rs └── test │ ├── NotoSerif-Regular.ttf │ ├── floor_nm.jpg │ ├── hornbeam2.png │ ├── mountains3_512.jpg │ ├── mountainsHgt.png │ ├── pattern.png │ ├── rpi3d.cpython-37m-arm-linux-gnueabihf.so │ ├── rust_pi3d.mtl │ ├── rust_pi3d.obj │ ├── sbox_back.jpg │ ├── sbox_bottom.jpg │ ├── sbox_front.jpg │ ├── sbox_left.jpg │ ├── sbox_right.jpg │ ├── sbox_top.jpg │ ├── test1.py │ ├── test2.py │ └── test3.py └── rust_pi3d.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rust_pi3d 2 | translation of pi3d from python to rust 3 | 4 | 5 | 6 | Following parts of the tutorial: 7 | http://nercury.github.io/rust/opengl/tutorial/2018/02/08/opengl-in-rust-from-scratch-01-window.html 8 | I have started the process of making a rust version of the python pi3d 9 | module. 10 | 11 | As at commit 12c692f most of the functionality is in place to get demos such 12 | as ForestWalk working. 13 | 14 | *Installation* 15 | 16 | For this to work you need to install rust. Basically follow the instructions 17 | here https://www.rust-lang.org/en-US/install.html It seems to be reasonably 18 | fool proof though I've not tried it on Windows yet. 19 | 20 | You also need to have SDL2 running. On linux it's pretty easy using 21 | 22 | ```sh 23 | patrick@thiscomputer:~/rust/rust_pi3d$ sudo apt-get install libsdl2-dev 24 | ``` 25 | 26 | See the tutorial link at the top or the rust sdl2 crate site for what to 27 | do for windows i.e. put the dll in the same folder as the exectuable. 28 | PS I have added the SDL2.dll v2.28.3-win32-x64 but you should 29 | download and install the one appropriate for your windows and machine. 30 | 31 | Then in the terminal navigate to wherever you cloned or extracted this 32 | repo and build the executables using cargo, and run them like this (NB 33 | now cd to the pi3d directory): 34 | 35 | ```sh 36 | patrick@thiscomputer:~/rust/rust_pi3d/pi3d$ cargo build --examples --release 37 | ``` 38 | then 39 | ``` 40 | patrick@thiscomputer:~/rust/rust_pi3d/pi3d$ target/release/examples/game 41 | patrick@thiscomputer:~/rust/rust_pi3d/pi3d$ target/release/examples/forest_walk 42 | ``` 43 | you only have to do the initial build once as this runs the build.rs script 44 | that copies over the examples dependencies. After that you can run examples using. 45 | ``` 46 | patrick@thiscomputer:~/rust/rust_pi3d/pi3d$ cargo run --example game --release 47 | ``` 48 | and all the source will be checked and recompiled as required. 49 | 50 | Building for release will take longer (maybe) and exclude debugging symbols etc but 51 | run faster (obviously) and will be much smaller. If you want to build for 52 | debug (probably sensible) exclude the `--release`. However if you do this 53 | the required support files in `target/release/textures`, `models`, `ecubes` 54 | and `fonts` will have to be copied into the `target/debug/` directory. 55 | 56 | On the Raspberry Pi the OpenGL used by default SDL2 won't work unless you use 57 | raspi-config and switch the graphics driver to the new experimental one. 58 | It should be possible to compile SDL2 to use the built in Broadcom drivers 59 | but I've not tried that. (Let me know if you do and what the problems are). 60 | 61 | TODO:: 62 | 63 | ~~installation, requirements and compile instructions on here!~~ 64 | 65 | ~~build script to copy support files (images, models, fonts etc) to target 66 | directory~~ 67 | 68 | ~~Fonts and lettering.~~ 69 | 70 | error and failure handling. Many functions need to return a Result<..> 71 | wrapper around whatever they are supposed to do. 72 | 73 | ~~Texture blender option (lower alpha to drop pixel)~~ 74 | 75 | Find out why last value of array_buffer is always set to zero (i.e. 76 | why a sacrificial extra one needs to be added) 77 | 78 | Mouse buttons 79 | 80 | Offscreen textures, screen capture and post processing 81 | 82 | Lifetimes and controlled deletion of Shaders and Programs. 83 | 84 | More elaborate Camera functions. 85 | 86 | Other Texture types i.e. different internal storage modes supported 87 | by OpenGL 88 | 89 | **As at 16 Dec 19 there are some trials making a python wrapper** 90 | 91 | *see pyo3_module directory* -------------------------------------------------------------------------------- /SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/SDL2.dll -------------------------------------------------------------------------------- /pi3d/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /pi3d/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2024" 3 | name = "pi3d" 4 | version = "0.2.0" 5 | authors = ["paddywwof "] 6 | build = "build.rs" 7 | 8 | [dependencies] 9 | sdl2 = "^0.32.0" 10 | gl = "^0.10" 11 | ndarray = "0.16" 12 | image = "0.21.3" 13 | rand = "^0.6.5" 14 | rusttype = "0.6" 15 | lazy_static = "^1.4" 16 | 17 | [build-dependencies] 18 | fs_extra = "^1.1" 19 | 20 | [profile.release] 21 | codegen-units = 1 22 | incremental = true 23 | -------------------------------------------------------------------------------- /pi3d/build.rs: -------------------------------------------------------------------------------- 1 | extern crate fs_extra; 2 | 3 | use std::env; 4 | 5 | fn main() { 6 | let host_triple = env::var("HOST").unwrap(); 7 | let targ_triple = env::var("TARGET").unwrap(); 8 | let target_dir = if targ_triple == host_triple { 9 | "".to_string() 10 | } else { 11 | format!("{}/", targ_triple) 12 | }; 13 | let profile = env::var("PROFILE").unwrap(); //ie debug or release 14 | let out_dir = format!("target/{}{}/examples", target_dir, profile); 15 | println!("this out_dir={:?}", out_dir); 16 | let mut options = fs_extra::dir::CopyOptions::new(); 17 | options.overwrite = true; 18 | 19 | let mut from_paths = vec![ 20 | "examples/textures", 21 | "examples/shaders", 22 | "examples/models", 23 | "examples/fonts", 24 | "examples/ecubes", 25 | "examples/cities", 26 | ]; 27 | if targ_triple.find("windows") != None { 28 | // will need dll for windows 29 | from_paths.push("../SDL2.dll"); 30 | } 31 | println!("{:?}", from_paths); 32 | fs_extra::copy_items(&from_paths, &out_dir, &options).unwrap(); 33 | } 34 | -------------------------------------------------------------------------------- /pi3d/examples/cities/cities150.txt: -------------------------------------------------------------------------------- 1 | -392.4,423.1 2 | 85.7,-207.2 3 | -294.4,-78.7 4 | -240.5,-48.5 5 | 21.7,94.8 6 | -379.5,-0.9 7 | -50.9,316.9 8 | -420.5,20.2 9 | -184.3,-37.6 10 | 297.6,-31.3 11 | -131.5,-134.9 12 | -223.1,-30.6 13 | -298.0,211.7 14 | 368.1,118.8 15 | 271.8,-327.7 16 | -98.5,44.1 17 | 439.5,284.9 18 | 2.2,-260.7 19 | 219.7,-209.7 20 | -249.4,294.9 21 | 371.7,405.4 22 | -318.8,-138.1 23 | -160.0,365.9 24 | 87.3,-319.0 25 | -315.9,335.1 26 | -218.2,-362.7 27 | 24.3,285.3 28 | 92.0,166.2 29 | 230.7,212.9 30 | 239.1,336.2 31 | 79.5,221.6 32 | 10.1,407.5 33 | -177.7,219.3 34 | -237.9,318.3 35 | 318.0,176.1 36 | -222.0,-5.1 37 | -365.2,-199.6 38 | 187.2,-265.6 39 | 100.8,-282.3 40 | 37.9,76.7 41 | -249.6,367.6 42 | 104.9,109.7 43 | -237.0,391.1 44 | 397.9,96.7 45 | -402.7,-116.7 46 | -301.6,361.7 47 | 39.4,-78.1 48 | -319.0,18.5 49 | 200.7,173.9 50 | -290.3,54.6 51 | 311.0,-135.3 52 | -324.9,4.1 53 | -28.8,1.1 54 | 417.4,361.9 55 | -58.5,295.2 56 | -336.9,340.3 57 | -447.2,-421.5 58 | -264.5,-189.1 59 | 48.9,293.4 60 | -218.2,166.2 61 | -165.9,120.6 62 | 15.9,164.3 63 | 243.9,446.5 64 | 118.5,256.3 65 | 158.4,223.9 66 | 330.8,-347.9 67 | -72.5,169.3 68 | -417.3,-428.2 69 | -75.0,-55.6 70 | 109.7,418.0 71 | 47.6,115.8 72 | -359.5,37.8 73 | 149.1,18.0 74 | 427.4,-219.9 75 | 59.3,158.7 76 | 433.5,-289.8 77 | 55.3,244.7 78 | 352.0,3.1 79 | -109.6,-124.6 80 | 435.3,325.0 81 | -125.0,149.6 82 | 427.8,99.9 83 | -430.8,32.9 84 | 176.1,393.6 85 | -223.8,401.4 86 | 208.4,113.2 87 | 50.3,310.4 88 | 365.8,-381.0 89 | 148.5,167.7 90 | -48.8,-285.2 91 | 26.4,-273.6 92 | -349.0,312.4 93 | 55.6,312.0 94 | 394.0,-174.7 95 | -339.5,-408.2 96 | -65.5,387.0 97 | 304.8,-360.3 98 | 55.6,-270.2 99 | -336.1,235.7 100 | -21.5,-148.4 101 | 353.2,100.8 102 | -355.0,427.4 103 | -74.7,-382.1 104 | -400.9,-14.4 105 | -156.2,-113.7 106 | -125.9,-178.8 107 | -247.4,-176.2 108 | 25.0,231.7 109 | 28.9,-29.4 110 | 223.4,94.7 111 | -292.1,388.6 112 | -343.1,-296.5 113 | 378.3,-407.0 114 | -408.1,365.6 115 | -444.2,-181.1 116 | -109.7,107.1 117 | -263.7,116.6 118 | 97.6,-418.6 119 | -444.2,-15.6 120 | 104.7,172.0 121 | 263.3,58.3 122 | 133.9,-411.4 123 | -203.8,-223.5 124 | -253.2,360.7 125 | 185.9,275.7 126 | -247.5,411.4 127 | 123.0,421.9 128 | -303.3,-187.0 129 | 194.3,-49.7 130 | -178.1,268.2 131 | -407.2,322.0 132 | -229.2,-51.1 133 | 352.5,421.5 134 | 374.2,18.3 135 | -45.1,-289.0 136 | 415.9,-79.3 137 | 381.9,-343.7 138 | 192.7,382.2 139 | -177.6,142.8 140 | 402.9,-0.2 141 | 438.1,291.2 142 | -193.2,6.7 143 | -146.0,301.3 144 | -382.2,-66.1 145 | 248.5,410.7 146 | -270.5,-99.6 147 | 97.1,171.7 148 | 409.3,-259.0 149 | 432.3,118.2 150 | -415.7,-439.2 151 | 152 | 153 | -------------------------------------------------------------------------------- /pi3d/examples/cities/cities200.txt: -------------------------------------------------------------------------------- 1 | -390.7,-319.6 2 | 273.8,-224.6 3 | -90.2,-122.6 4 | 6.8,330.5 5 | 35.5,-64.8 6 | 155.5,-17.4 7 | -96.9,-77.3 8 | -201.0,219.4 9 | -40.6,121.9 10 | 319.6,162.5 11 | -242.6,-380.2 12 | -298.1,-61.9 13 | -352.4,202.0 14 | 293.3,307.0 15 | -246.2,354.9 16 | -185.8,31.0 17 | -334.8,202.5 18 | 95.3,0.6 19 | 141.8,-222.7 20 | -261.6,-87.5 21 | -18.9,161.7 22 | -377.3,-91.3 23 | 186.6,-378.0 24 | -61.7,91.0 25 | 327.7,-6.7 26 | 3.5,123.6 27 | 166.2,-317.8 28 | 91.9,-125.4 29 | 107.0,-80.4 30 | 227.9,213.7 31 | 43.5,-111.7 32 | 150.7,-165.1 33 | 348.2,-192.0 34 | -312.5,-313.5 35 | -28.8,-20.3 36 | -217.5,-182.2 37 | -367.8,377.2 38 | -277.5,93.7 39 | 309.9,-94.9 40 | 350.0,288.3 41 | -363.3,-203.7 42 | -190.0,305.9 43 | 139.5,373.9 44 | 51.6,-349.5 45 | 247.4,100.1 46 | 243.6,-265.1 47 | 39.6,49.1 48 | 320.2,-25.6 49 | -77.6,-191.7 50 | 214.3,-211.9 51 | 330.2,-269.4 52 | 187.2,75.4 53 | -241.9,-204.2 54 | 262.5,98.2 55 | -40.9,-203.7 56 | -52.2,-300.6 57 | 94.8,323.8 58 | -317.9,-257.8 59 | -57.2,-234.7 60 | -59.2,318.3 61 | 162.8,121.6 62 | 202.3,-291.3 63 | 47.7,319.7 64 | 283.0,-239.3 65 | 49.9,223.8 66 | -232.8,-175.7 67 | 277.4,30.7 68 | 176.9,-143.4 69 | -342.0,-114.8 70 | -55.3,9.1 71 | 62.1,371.2 72 | -75.2,247.3 73 | -43.1,238.6 74 | -17.3,197.3 75 | -263.1,293.4 76 | 282.6,157.8 77 | 347.3,278.2 78 | -341.6,-212.1 79 | 270.1,-346.6 80 | 231.2,-112.5 81 | 90.8,373.0 82 | 88.0,-9.5 83 | -109.7,30.0 84 | 284.5,-275.9 85 | 305.4,-355.8 86 | -18.0,-98.8 87 | -270.3,-112.0 88 | -197.8,281.3 89 | -360.5,378.3 90 | -335.5,348.7 91 | 41.2,262.8 92 | 103.8,-92.5 93 | -213.3,128.0 94 | 90.6,-227.7 95 | -56.9,-162.7 96 | -360.3,247.9 97 | 368.2,-175.4 98 | 26.8,-242.8 99 | -22.4,-180.5 100 | 325.2,-15.5 101 | -303.4,-103.3 102 | -233.1,54.1 103 | 171.6,-375.4 104 | -195.1,-306.1 105 | -168.5,-172.4 106 | 5.5,-341.8 107 | -127.1,-57.4 108 | -321.2,-266.9 109 | -287.3,339.9 110 | -286.1,113.7 111 | 309.7,162.2 112 | -311.0,-79.2 113 | -38.3,215.9 114 | -180.3,275.5 115 | -198.1,-53.4 116 | 277.9,111.2 117 | 18.1,-192.3 118 | 209.6,142.9 119 | -111.1,208.5 120 | -339.8,-51.0 121 | 233.2,-219.5 122 | 38.6,-179.5 123 | -322.6,268.3 124 | -324.8,-42.9 125 | 295.9,35.9 126 | 223.7,37.3 127 | -49.4,-64.8 128 | -358.0,-272.4 129 | -282.0,165.3 130 | 292.7,5.7 131 | -146.5,-191.1 132 | 213.0,384.9 133 | -371.0,-371.2 134 | -215.2,182.1 135 | 104.9,-391.8 136 | -60.5,-103.7 137 | -114.4,332.9 138 | 152.4,-107.3 139 | 31.3,106.4 140 | 291.8,-268.6 141 | 201.4,300.1 142 | -133.5,-233.3 143 | -332.9,363.1 144 | -107.1,-34.4 145 | -318.0,20.6 146 | 190.0,385.9 147 | 153.2,-124.8 148 | -320.6,345.9 149 | -293.8,-313.1 150 | -335.2,54.3 151 | 33.2,348.6 152 | 284.5,-95.3 153 | 202.2,108.9 154 | -215.2,373.0 155 | 104.8,319.1 156 | 361.0,359.2 157 | 306.6,348.5 158 | 119.1,103.6 159 | -273.7,243.8 160 | -287.4,-247.2 161 | -134.4,213.2 162 | -279.6,339.7 163 | 94.3,-251.0 164 | -391.9,115.7 165 | -165.2,-56.3 166 | -281.9,14.7 167 | 116.0,17.2 168 | 53.5,-349.0 169 | -384.9,377.6 170 | -200.3,-356.1 171 | -305.4,-147.1 172 | -53.0,-152.5 173 | 118.9,-23.0 174 | -316.7,-347.1 175 | 17.6,53.0 176 | -73.3,244.5 177 | -143.9,-49.2 178 | -228.1,78.3 179 | 333.9,50.2 180 | 281.9,340.3 181 | 187.5,-144.7 182 | -258.1,36.3 183 | 96.8,339.6 184 | -274.7,-6.2 185 | 321.6,-144.8 186 | -96.4,-88.6 187 | 125.9,-286.9 188 | 367.2,302.5 189 | -36.5,372.3 190 | -206.3,-28.7 191 | 135.0,-243.3 192 | 87.1,94.6 193 | 47.0,167.6 194 | -121.1,272.4 195 | 390.9,145.1 196 | -322.8,366.8 197 | 79.9,-223.4 198 | 366.4,0.9 199 | -277.2,26.2 200 | 329.5,-226.1 -------------------------------------------------------------------------------- /pi3d/examples/cities/cities30.txt: -------------------------------------------------------------------------------- 1 | -203.9,342.7 2 | 162.3,-101.4 3 | 213.2,-149.7 4 | 296.8,29.9 5 | -113.3,321.2 6 | 382.8,-348.6 7 | -154.7,154.4 8 | 56.0,266.7 9 | 121.4,98.3 10 | -71.1,-39.0 11 | 224.8,-40.4 12 | 49.2,-48.1 13 | -146.9,190.1 14 | 145.4,0.7 15 | 305.6,-424.7 16 | -204.1,-92.6 17 | -199.7,-366.6 18 | 417.6,250.3 19 | -87.8,-0.6 20 | 285.2,216.2 21 | -328.5,422.5 22 | -139.0,-398.6 23 | 67.6,-62.5 24 | 8.2,437.4 25 | 280.4,-448.7 26 | 202.5,-178.4 27 | -55.8,115.5 28 | -424.1,-20.0 29 | -83.2,-81.1 30 | -327.6,76.2 31 | 32 | -------------------------------------------------------------------------------- /pi3d/examples/cities/cities50.txt: -------------------------------------------------------------------------------- 1 | -235.6,254.6 2 | -286.8,-420.9 3 | -125.3,47.5 4 | 23.4,97.1 5 | -361.2,-432.5 6 | -343.5,221.2 7 | -238.0,-322.2 8 | 308.5,-93.6 9 | -254.3,-92.4 10 | -242.8,-291.7 11 | -281.7,108.6 12 | -204.7,-366.7 13 | -115.2,298.2 14 | -365.9,208.2 15 | 443.6,111.1 16 | 405.6,-192.0 17 | -111.0,-195.3 18 | -33.2,-140.4 19 | 215.1,-84.9 20 | -243.4,410.9 21 | -407.6,-159.4 22 | 392.7,346.0 23 | 429.0,-170.4 24 | 217.6,310.0 25 | 204.5,294.6 26 | -224.8,-86.4 27 | 198.1,-397.2 28 | -249.5,198.5 29 | -10.1,274.2 30 | 428.4,-138.0 31 | -265.9,110.0 32 | -147.4,-264.3 33 | -439.2,293.7 34 | 121.6,187.6 35 | 372.9,-209.9 36 | -331.9,-110.5 37 | -269.2,112.8 38 | 408.7,308.7 39 | -32.9,-197.7 40 | -231.4,-423.3 41 | -90.8,-209.8 42 | -358.4,-151.0 43 | -26.1,-5.3 44 | -80.6,121.2 45 | -52.6,-113.9 46 | 82.7,190.9 47 | -397.1,125.4 48 | -182.0,151.1 49 | -10.7,393.9 50 | 377.7,-85.8 51 | 52 | -------------------------------------------------------------------------------- /pi3d/examples/cities/cities80.txt: -------------------------------------------------------------------------------- 1 | 295.00,198.00 2 | 153.00,-365.00 3 | 169.00,306.00 4 | 26.00,59.00 5 | 94.00,-49.00 6 | -142.00,-95.00 7 | 335.00,154.00 8 | -168.00,78.00 9 | -113.00,-149.00 10 | 256.00,173.00 11 | -231.00,128.00 12 | 164.00,335.00 13 | 252.00,-250.00 14 | -248.00,-340.00 15 | -87.00,-18.00 16 | -159.00,-236.00 17 | 361.00,-196.00 18 | -65.00,162.00 19 | -326.00,167.00 20 | -129.00,-210.00 21 | -172.00,364.00 22 | 28.00,-229.00 23 | -270.00,37.00 24 | -144.00,361.00 25 | -262.00,-281.00 26 | 321.00,-232.00 27 | 381.00,230.00 28 | -56.00,94.00 29 | 187.00,164.00 30 | 353.00,-99.00 31 | 251.30,-247.70 32 | -284.00,201.70 33 | -25.70,24.60 34 | -121.00,170.70 35 | 76.70,-102.70 36 | -133.30,-143.60 37 | -140.00,123.50 38 | 28.50,-25.00 39 | -332.00,-58.90 40 | 178.20,283.10 41 | -211.10,-60.40 42 | -171.80,-239.80 43 | -189.50,-116.80 44 | 190.30,237.50 45 | 93.50,171.60 46 | -359.20,-101.30 47 | -289.40,-73.30 48 | -274.20,-254.00 49 | 86.80,142.90 50 | -318.70,31.80 51 | 126.90,292.50 52 | 115.00,-56.70 53 | 40.50,254.60 54 | 1.40,321.20 55 | 13.10,-21.20 56 | 13.70,365.60 57 | 277.10,-216.90 58 | 35.30,-44.50 59 | 162.70,38.00 60 | 76.10,12.70 61 | -112.30,-84.40 62 | 265.00,78.60 63 | -115.30,-81.30 64 | -338.20,75.80 65 | 132.60,154.90 66 | -235.10,18.70 67 | 60.80,-276.00 68 | 168.60,303.50 69 | 87.60,242.40 70 | 92.60,-211.60 71 | 99.90,281.70 72 | 226.70,-97.20 73 | -182.40,199.20 74 | -193.80,41.10 75 | 162.70,361.90 76 | 223.60,-200.00 77 | 68.80,171.70 78 | 145.10,-255.60 79 | -150.40,177.20 80 | 97.70,-213.20 81 | 82 | -------------------------------------------------------------------------------- /pi3d/examples/ecubes/License.txt: -------------------------------------------------------------------------------- 1 | Sincere thank you to Jockum Skoglund aka 'hipshot' who created these fantastic environment cubes; Miramar, Grimmnight, interstellar, stormydays and violentday under the following licence: "Modify however you like, just cred me for my work, maybe link to my page". 2 | 3 | The textures are available here: http://www.zfight.com/misc/images/textures/envmaps/ 4 | 5 | and 6 | 7 | http://www.zfight.com/misc/files/textures/ 8 | -------------------------------------------------------------------------------- /pi3d/examples/ecubes/README.TXT: -------------------------------------------------------------------------------- 1 | THIS SKY WAS UPDATED AT THE 27TH 2 | THE ORIG HAD SOME ERRORS 3 | 4 | MIRAMAR 5 | high res 1024^2 environment map 6 | ships as TGA. 7 | 8 | 9 | By Jockum Skoglund aka hipshot 10 | hipshot@zfight.com 11 | www.zfight.com 12 | Stockholm, 2005 08 25 13 | 14 | 15 | Modify however you like, just cred me for my work, maybe link to my page. 16 | -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_back.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_bottom.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_front.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_left.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_right.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/miramar_256_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/miramar_256_top.png -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_back.jpg -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_bottom.jpg -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_front.jpg -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_left.jpg -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_right.jpg -------------------------------------------------------------------------------- /pi3d/examples/ecubes/sbox_top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/ecubes/sbox_top.jpg -------------------------------------------------------------------------------- /pi3d/examples/farris.rs: -------------------------------------------------------------------------------- 1 | extern crate pi3d; 2 | extern crate sdl2; 3 | use sdl2::keyboard::Keycode; 4 | 5 | const W: f32 = 1200.0; 6 | const H: f32 = 720.0; 7 | const UNIF_OFFSET: usize = 11; // first unused row of unif 8 | const PARAMS: &[[f32; 3]; 8] = &[ 9 | [1.0, 4.0, -0.2], 10 | [0.2, -5.0, -2.0], 11 | [ 12 | 0.1, 0.2, //L-n1,m1,ar1,ai1,n2,m2,ar2,ai2 13 | 1.0, 14 | ], 15 | [4.0, -0.2, 0.2], 16 | [-5.0, -2.0, 0.1], 17 | [ 18 | 0.2, //L-n3,m3,ar3,ai3 R-n1,m1,ar1,ai1 19 | 1.0, 0.0, 20 | ], 21 | [0.0, 0.0, 0.0], 22 | [0.0, 0.0, 0.0], 23 | ]; //R-n2,n2,m2,ar2,ai2,n3,m3,ar3,ai3 24 | 25 | fn reset_params(obj: &mut pi3d::shape::Shape) { 26 | for i in 0..PARAMS.len() { 27 | for j in 0..3 { 28 | obj.unif[[UNIF_OFFSET + i, j]] = PARAMS[i][j]; 29 | } 30 | } 31 | } 32 | 33 | fn main() { 34 | // setup display 35 | let mut display = pi3d::display::create("Farris page 67", W, H, "GL", 2, 1).unwrap(); 36 | display.set_background(&[0.1, 0.1, 0.2, 1.0]); 37 | display.set_mouse_relative(true); 38 | display.set_target_fps(1000.0); 39 | 40 | // shaders 41 | let shader = pi3d::shader::Program::from_res("shaders/farris_p67b").unwrap(); 42 | let textsh = pi3d::shader::Program::from_res("uv_pointsprite").unwrap(); 43 | //let shader = pi3d::shader::Program::from_res("shaders/farris_p67b_ES30").unwrap(); 44 | //let textsh = pi3d::shader::Program::from_res("shaders/uv_pointsprite_ES30").unwrap(); 45 | 46 | // cameras 47 | let mut camera = pi3d::camera::create(&display); 48 | let mut camera2d = pi3d::camera::create(&display); 49 | camera2d.set_3d(false); 50 | 51 | // textures 52 | let tex = pi3d::texture::create_from_file("textures/poppy1.jpg"); 53 | 54 | // cube 55 | let mut cube = 56 | pi3d::shapes::cuboid::create(camera.reference(), 10.0, 10.0, 10.0, 1.0, 1.0, 1.0); 57 | cube.set_draw_details(&shader, &vec![tex.id], 1.0, 0.0, 0.1, 0.1, 0.0); 58 | cube.position_z(50.0); 59 | cube.buf[0].unib[[3, 0]] = 0.05; 60 | 61 | // plane 62 | let mut plane = pi3d::shapes::plane::create(camera2d.reference(), W, H); 63 | plane.set_draw_details(&shader, &vec![tex.id], 1.0, 0.0, 0.1, 0.1, 0.0); 64 | plane.position_z(9900.0); 65 | plane.buf[0].unib[[3, 0]] = 0.05; 66 | 67 | reset_params(&mut cube); 68 | reset_params(&mut plane); 69 | 70 | // fps counter 71 | let font = pi3d::util::font::create("fonts/NotoSans-Regular.ttf", "", "", 64.0); 72 | let mut fps_text = pi3d::shapes::point_text::create(camera2d.reference(), &font, 20, 24.0); 73 | fps_text.set_shader(&textsh); 74 | let fps_blk = fps_text.add_text_block( 75 | &font, 76 | &[-W * 0.5 + 20.0, -H * 0.5 + 20.0, 0.1], 77 | 19, 78 | "00.0 FPS", 79 | ); 80 | 81 | let mut x: f32 = 0.0; 82 | let mut y: f32 = 0.0; 83 | let mut z: f32 = -0.1; 84 | let mut df: f32 = 0.01; // for/aft 85 | let mut ds: f32 = 0.0; // side/side 86 | let mut rot: f32 = 0.0; 87 | let mut tilt: f32 = 0.0; 88 | let mut fr_num: u32 = 0; 89 | let mut param_point: usize = 0; 90 | 91 | while display.loop_running() { 92 | fr_num += 1; 93 | if fr_num > 2000 { 94 | // this changes which parameter to alter 95 | fr_num = 0; 96 | param_point += 1; 97 | if param_point >= (17) { 98 | param_point = 0; 99 | } 100 | } 101 | cube.draw(); 102 | plane.draw(); 103 | if x.abs() > 300.0 { // draw tiled maps 104 | //TODO some kind of navigation 105 | } 106 | if z.abs() > 300.0 { 107 | //TODO 108 | } 109 | fps_text.set_text(&font, fps_blk, &format!("{:5.1} FPS", display.fps())); 110 | fps_text.draw(); 111 | 112 | if display.keys_pressed.contains(&Keycode::Escape) { 113 | break; 114 | } 115 | if display.mouse_moved { 116 | tilt = display.mouse_y as f32 * -0.004; 117 | rot = display.mouse_x as f32 * -0.004; 118 | } 119 | 120 | if display.keys_pressed.contains(&Keycode::W) { 121 | df = 0.2 122 | } 123 | if display.keys_pressed.contains(&Keycode::S) { 124 | df = -0.15; 125 | } 126 | if display.keys_pressed.contains(&Keycode::A) { 127 | ds = 0.15; 128 | } 129 | if display.keys_pressed.contains(&Keycode::D) { 130 | ds = -0.15; 131 | } 132 | if display.keys_pressed.contains(&Keycode::R) { 133 | reset_params(&mut cube); 134 | reset_params(&mut plane); 135 | } 136 | let cd = camera.get_direction(); 137 | let dx = cd[0] * df - cd[2] * ds; 138 | x += dx; 139 | y += cd[1] * df; 140 | let dz = cd[2] * df + cd[0] * ds; 141 | z += dz; 142 | camera.reset(); 143 | camera.rotate(&[tilt, rot, 0.0]); 144 | if ds != 0.0 || df != 0.0 { 145 | camera.position(&[x, y, z]); 146 | let param_r = param_point / 3; 147 | let param_c = param_point - (param_r * 3); 148 | cube.unif[[param_r + UNIF_OFFSET, param_c]] += dx * 0.1; 149 | plane.unif[[param_r + UNIF_OFFSET, param_c]] += dx * 0.1; 150 | let o_param_point = (param_point + 8) % 16; // modulus keep in range 151 | let param_r = o_param_point / 3; 152 | let param_c = o_param_point - (param_r * 3); 153 | cube.unif[[param_r + UNIF_OFFSET, param_c]] += dz * 0.1; 154 | plane.unif[[param_r + UNIF_OFFSET, param_c]] += dz * 0.1; 155 | //println!("{},{},{}", param_r, param_c, plane.unif[[param_r + UNIF_OFFSET, param_c]]) 156 | } 157 | //cube.unif[[16, 1]] = fr_num as f32 * 0.001571; 158 | //plane.unif[[16, 1]] = fr_num as f32 * 0.001571; 159 | df = 0.0; 160 | ds = 0.0; 161 | 162 | /* // TODO world wrapping 163 | if x.abs() >= halfsize { 164 | x -= x.signum() * mapsize; 165 | } 166 | if z.abs() >= halfsize { 167 | z -= z.signum() * mapsize; 168 | }*/ 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /pi3d/examples/fonts/NotoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/fonts/NotoSans-Regular.ttf -------------------------------------------------------------------------------- /pi3d/examples/fonts/NotoSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/fonts/NotoSerif-Regular.ttf -------------------------------------------------------------------------------- /pi3d/examples/fonts/Str437.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/fonts/Str437.ttf -------------------------------------------------------------------------------- /pi3d/examples/game.rs: -------------------------------------------------------------------------------- 1 | extern crate pi3d; 2 | extern crate rand; 3 | extern crate sdl2; 4 | use sdl2::keyboard::Keycode; 5 | 6 | const W: f32 = 960.0; 7 | const H: f32 = 720.0; 8 | 9 | fn main() { 10 | let mut display = pi3d::display::create("experimental game window", W, H, "GL", 2, 1).unwrap(); 11 | display.set_background(&[0.1, 0.1, 0.2, 1.0]); 12 | display.set_mouse_relative(true); 13 | display.set_target_fps(30.0); 14 | let shader_program = pi3d::shader::Program::from_res("uv_reflect").unwrap(); 15 | let flatsh = pi3d::shader::Program::from_res("uv_flat").unwrap(); 16 | let textsh = pi3d::shader::Program::from_res("uv_pointsprite").unwrap(); 17 | let mut camera = pi3d::camera::create(&display); 18 | let mut camera2d = pi3d::camera::create(&display); 19 | camera2d.set_3d(false); 20 | 21 | let tex = pi3d::texture::create_from_file("textures/pattern.png"); 22 | let maptex = pi3d::texture::create_from_file("textures/mountains3_512.jpg"); 23 | let mapnorm = pi3d::texture::create_from_file("textures/grasstile_n.jpg"); 24 | let stars = pi3d::texture::create_from_file("textures/stars.jpg"); 25 | let font = pi3d::util::font::create("fonts/NotoSans-Regular.ttf", "", "ęĻ", 64.0); 26 | let mut mystring = pi3d::shapes::string::create( 27 | camera2d.reference(), 28 | &font, 29 | "\"The quick brown 30 | fox `jumps` 31 | over thę Ļazy 32 | dog\"", 33 | 0.0, 34 | ); 35 | mystring.set_shader(&flatsh); 36 | mystring.position_z(2.0); 37 | 38 | let mut candlestick = pi3d::shapes::lathe::create( 39 | camera.reference(), 40 | vec![ 41 | [0.0, 2.0], 42 | [0.1, 1.8], 43 | [0.1, 1.2], 44 | [0.5, 1.0], 45 | [0.6, 0.6], 46 | [0.2, 0.5], 47 | [0.2, 0.2], 48 | [1.0, 0.1], 49 | [1.2, -0.3], 50 | [0.0, -2.0], 51 | ], 52 | 144, 53 | 0.0, 54 | 1.0, 55 | ); 56 | candlestick.set_draw_details( 57 | &shader_program, 58 | &vec![tex.id, mapnorm.id, stars.id], 59 | 1.0, 60 | 0.1, 61 | 1.0, 62 | 1.0, 63 | 1.0, 64 | ); 65 | candlestick.position(&[-2.0, 30.0, 15.0]); 66 | candlestick.set_material(&[1.0, 0.0, 0.0]); 67 | 68 | let sphere = 69 | pi3d::shapes::sphere::create(camera.reference(), 1.5, 16, 32, 0.3, false).reference(); 70 | sphere.borrow_mut().set_textures(&vec![tex.id, mapnorm.id]); 71 | sphere.borrow_mut().set_shader(&shader_program); 72 | 73 | let mut cube2 = pi3d::shapes::cuboid::create(camera.reference(), 3.0, 2.0, 1.0, 1.0, 1.0, 1.0); 74 | cube2.set_draw_details( 75 | &shader_program, 76 | &vec![tex.id, mapnorm.id, stars.id], 77 | 2.0, 78 | 0.1, 79 | 2.0, 80 | 3.0, 81 | 1.0, 82 | ); 83 | cube2.set_light( 84 | 0, 85 | &[1.5, 1.5, 4.0], 86 | &[10.0, 10.0, 10.0], 87 | &[0.05, 0.1, 0.05], 88 | true, 89 | ); 90 | cube2.add_child(sphere.clone()); 91 | 92 | let mut junk = pi3d::shapes::merge_shape::create(camera.reference()); 93 | pi3d::shapes::merge_shape::add_shapes( 94 | &mut junk, 95 | vec![&cube2, &cube2, &candlestick], 96 | vec![[2.0, 1.0, 1.0], [-1.0, -1.0, 1.0], [0.0, 0.0, -0.5]], 97 | vec![[0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [0.0, 0.0, 0.0]], 98 | vec![[1.0, 1.0, 1.0], [0.5, 2.0, 2.0], [2.2, 2.2, 2.2]], 99 | vec![0, 0, 1], 100 | ); 101 | junk.buf[1].set_material(&[1.0, 1.0, 0.0, 1.0]); 102 | junk.position(&[1.0, 30.0, 7.5]); 103 | 104 | let mut map = pi3d::shapes::elevation_map::new( 105 | camera.reference(), 106 | "textures/mountainsHgt.png", 107 | 400.0, 108 | 400.0, 109 | 50.0, 110 | 64, 111 | 64, 112 | 1.0, 113 | "nothing", 114 | ); 115 | map.shape.set_draw_details( 116 | &shader_program, 117 | &vec![maptex.id, mapnorm.id, stars.id], 118 | 128.0, 119 | 0.0, 120 | 1.0, 121 | 1.0, 122 | 2.0, 123 | ); 124 | 125 | let (mut iss, _texlist) = pi3d::shapes::model_obj::create(camera.reference(), "models/iss.obj"); 126 | iss.set_shader(&shader_program); 127 | iss.set_normal_shine(&vec![mapnorm.id, stars.id], 16.0, 0.1, 1.0, 1.0, 0.1, true); 128 | iss.position(&[20.0, 50.0, 10.0]); 129 | iss.scale(&[40.0, 40.0, 40.0]); 130 | 131 | let mut clust = pi3d::shapes::merge_shape::create(camera.reference()); 132 | pi3d::shapes::merge_shape::cluster( 133 | &mut clust, &cube2, &map, -20.0, -100.0, 200.0, 150.0, 0.5, 2.5, 200, 134 | ); 135 | 136 | let (mut ecube, _tex_list) = pi3d::shapes::environment_cube::create( 137 | camera.reference(), 138 | 500.0, 139 | "ecubes/miramar_256", 140 | "png", 141 | ); 142 | ecube.set_shader(&flatsh); 143 | 144 | // fps counter 145 | let mut fps_text = pi3d::shapes::point_text::create(camera2d.reference(), &font, 20, 24.0); 146 | fps_text.set_shader(&textsh); 147 | let fps_blk = fps_text.add_text_block( 148 | &font, 149 | &[-W * 0.5 + 20.0, -H * 0.5 + 20.0, 0.1], 150 | 19, 151 | "00.0 FPS", 152 | ); 153 | 154 | let mut t: f32 = 0.0; 155 | let mut x: f32 = 0.0; 156 | let mut y: f32 = 0.0; 157 | let mut z: f32 = -0.1; 158 | let mut ds: f32 = 0.01; 159 | let mut rot: f32 = 0.0; 160 | let mut tilt: f32 = 0.0; 161 | 162 | while display.loop_running() { 163 | t += 0.02; 164 | 165 | sphere.borrow_mut().rotate_inc_y(0.01); 166 | sphere.borrow_mut().rotate_inc_z(0.031); 167 | sphere.borrow_mut().position(&[ 168 | (t * 0.087 % 2.2 - 1.1).abs(), 169 | (t * 0.12 % 5.98 - 2.99).abs() + 4.0, 170 | 2.5, 171 | ]); 172 | 173 | cube2.rotate_inc_z(0.009); 174 | cube2.position_x(((t + 0.7) * 0.047 % 5.2 - 2.6).abs() - 1.01); 175 | cube2.position_y((t * 0.092 % 3.48 - 1.74).abs() + 30.7); 176 | 177 | candlestick.rotate_inc_x(0.05); 178 | 179 | junk.rotate_inc_y(0.1); 180 | 181 | iss.rotate_inc_y(0.01); 182 | iss.rotate_inc_x(0.007); 183 | 184 | for i in 0..clust.buf[0].array_buffer.shape()[0] { 185 | clust.buf[0].array_buffer[[i, 1]] *= 0.9995 + 0.001 * rand::random::(); 186 | } 187 | clust.buf[0].re_init(); 188 | 189 | ecube.draw(); 190 | cube2.draw(); 191 | candlestick.draw(); 192 | junk.draw(); 193 | map.shape.draw(); 194 | iss.draw(); 195 | clust.draw(); 196 | mystring.draw(); 197 | fps_text.set_text(&font, fps_blk, &format!("{:5.1} FPS", display.fps())); 198 | fps_text.draw(); 199 | 200 | if display.keys_pressed.contains(&Keycode::Escape) { 201 | break; 202 | } 203 | if display.keys_down.contains(&Keycode::A) { 204 | cube2.offset(&[t % 3.0, 0.0, 0.0]); 205 | } 206 | if display.mouse_moved { 207 | tilt = (display.mouse_y as f32 - 300.0) * -0.004; 208 | rot = (display.mouse_x as f32 - 400.0) * -0.004; 209 | } 210 | if display.keys_pressed.contains(&Keycode::L) { 211 | candlestick.buf[0].set_line_width(2.0, true, false); 212 | } 213 | if display.keys_pressed.contains(&Keycode::F) { 214 | candlestick.buf[0].set_line_width(0.0, true, false); 215 | } 216 | if display.keys_pressed.contains(&Keycode::P) { 217 | candlestick.buf[0].set_point_size(3.0); 218 | } 219 | if display.keys_pressed.contains(&Keycode::W) { 220 | ds = 1.25; 221 | } 222 | if display.keys_pressed.contains(&Keycode::S) { 223 | ds = -0.25; 224 | } 225 | let cd = camera.get_direction(); 226 | x += cd[0] * ds; 227 | y += cd[1] * ds; 228 | z += cd[2] * ds; 229 | camera.reset(); 230 | camera.rotate(&[tilt, rot, 0.0]); 231 | if ds != 0.0 { 232 | let (newy, _mapnorm) = map.calc_height(x, z); 233 | y = newy + 5.0; 234 | camera.position(&[x, y, z]); 235 | } 236 | ds = 0.0; 237 | if display.was_resized() { 238 | camera.set_lens_from_display(&display); 239 | camera2d.set_lens_from_display(&display); 240 | fps_text.set_position( 241 | &font, 242 | fps_blk, 243 | &[ 244 | -display.width * 0.5 + 20.0, 245 | -display.height * 0.5 + 20.0, 246 | 0.1, 247 | ], 248 | ); 249 | } 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /pi3d/examples/minimal.rs: -------------------------------------------------------------------------------- 1 | extern crate pi3d; 2 | 3 | const W: f32 = 900.0; // these are overwritten by fullscreen option 4 | const H: f32 = 700.0; 5 | 6 | fn main() { 7 | // initially set up display, shader, camera, texture and shapes 8 | let mut display = 9 | pi3d::display::create("minimal example ESC to quit", W, H, "GL", 2, 1).unwrap(); 10 | display.set_target_fps(5.0); // nothing happens so no point running faster 11 | let shader = pi3d::shader::Program::from_res("uv_flat").unwrap(); 12 | let mut camera = pi3d::camera::create(&display); 13 | camera.set_3d(false); // make it a 2D shader 14 | let tex = pi3d::texture::create_from_file("textures/pattern.png"); 15 | let mut plane = pi3d::shapes::plane::create( 16 | camera.reference(), 17 | display.height * 0.7, 18 | display.height * 0.7, 19 | ); 20 | plane.set_draw_details(&shader, &vec![tex.id], 1.0, 0.0, 1.0, 1.0, 0.0); 21 | 22 | // draw in a loop 23 | while display.loop_running() { 24 | // default sdl2 check for ESC or click cross 25 | plane.draw(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /pi3d/examples/models/CargoHoldBaked2.mtl: -------------------------------------------------------------------------------- 1 | # 2 | # Wavefront material file 3 | # Converted by Meshlab Group 4 | # 5 | 6 | newmtl ashphalt 7 | Ka 0.200000 0.200000 0.200000 8 | Kd 1.000000 1.000000 1.000000 9 | Ks 1.000000 1.000000 1.000000 10 | Tr 1.000000 11 | illum 2 12 | Ns 0.000000 13 | map_Kd maps/ashphalt.jpg 14 | 15 | newmtl ashphalt_[barriers] 16 | Ka 0.200000 0.200000 0.200000 17 | Kd 1.000000 1.000000 1.000000 18 | Ks 1.000000 1.000000 1.000000 19 | Tr 1.000000 20 | illum 0 21 | Ns 0.000000 22 | map_Kd maps/barriersCompleteMap.jpg 23 | newmtl walkplate 24 | Ka 0.200000 0.200000 0.200000 25 | Kd 1.000000 1.000000 1.000000 26 | Ks 1.000000 1.000000 1.000000 27 | Tr 1.000000 28 | illum 2 29 | Ns 0.000000 30 | map_Kd maps/walkplate.png 31 | 32 | newmtl orig_ashphaltShaded_[strips] 33 | Ka 0.200000 0.200000 0.200000 34 | Kd 1.000000 1.000000 1.000000 35 | Ks 0.200000 0.200000 0.200000 36 | Tr 1.000000 37 | illum 2 38 | Ns 0.000000 39 | map_Kd maps/stripsCompleteMap.jpg 40 | newmtl blueglow 41 | Ka 0.200000 0.200000 0.200000 42 | Kd 1.000000 1.000000 1.000000 43 | Ks 1.000000 1.000000 1.000000 44 | Tr 1.000000 45 | illum 0 46 | Ns 0.000000 47 | map_Kd maps/blueglow.png 48 | 49 | newmtl whiteLight 50 | Ka 0.200000 0.200000 0.200000 51 | Kd 1.000000 1.000000 1.000000 52 | Ks 1.000000 1.000000 1.000000 53 | Tr 1.000000 54 | illum 0 55 | Ns 0.000000 56 | map_Kd maps/white.png 57 | 58 | newmtl red 59 | Ka 0.200000 0.200000 0.200000 60 | Kd 1.000000 1.000000 1.000000 61 | Ks 1.000000 1.000000 1.000000 62 | Tr 1.000000 63 | illum 0 64 | Ns 0.000000 65 | map_Kd maps/red.png 66 | 67 | newmtl chevrons_[Line68] 68 | Ka 0.200000 0.200000 0.200000 69 | Kd 1.000000 1.000000 1.000000 70 | Ks 1.000000 1.000000 1.000000 71 | Tr 1.000000 72 | illum 0 73 | Ns 0.000000 74 | map_Kd maps/ChevronsCompleteMap.jpg 75 | newmtl panels 76 | Ka 0.200000 0.200000 0.200000 77 | Kd 1.000000 1.000000 1.000000 78 | Ks 1.000000 1.000000 1.000000 79 | Tr 1.000000 80 | illum 2 81 | Ns 0.000000 82 | map_Kd maps/fx3_Panels.png 83 | 84 | newmtl walkplate_[walkways] 85 | Ka 0.200000 0.200000 0.200000 86 | Kd 1.000000 1.000000 1.000000 87 | Ks 1.000000 1.000000 1.000000 88 | Tr 1.000000 89 | illum 0 90 | Ns 0.000000 91 | map_Kd maps/walkwaysCompleteMap.jpg 92 | 93 | newmtl panels_[body] 94 | Ka 0.200000 0.200000 0.200000 95 | Kd 1.000000 1.000000 1.000000 96 | Ks 1.000000 1.000000 1.000000 97 | Tr 1.000000 98 | illum 0 99 | Ns 0.000000 100 | map_Kd maps/bodyCompleteMap.jpg 101 | 102 | 103 | newmtl orig_bluealum_[bluealum] 104 | Ka 0.200000 0.200000 0.200000 105 | Kd 1.000000 1.000000 1.000000 106 | Ks 1.000000 1.000000 1.000000 107 | Tr 1.000000 108 | illum 0 109 | Ns 0.000000 110 | map_Kd maps/bluealumCompleteMap.jpg 111 | 112 | newmtl medmon 113 | Ka 0.200000 0.200000 0.200000 114 | Kd 1.000000 1.000000 1.000000 115 | Ks 1.000000 1.000000 1.000000 116 | Tr 1.000000 117 | illum 0 118 | Ns 0.000000 119 | map_Kd maps/MedMon1.png 120 | 121 | newmtl radar 122 | Ka 0.200000 0.200000 0.200000 123 | Kd 1.000000 1.000000 1.000000 124 | Ks 1.000000 1.000000 1.000000 125 | Ke 1.5 1.5 1.5 126 | Tr 1.000000 127 | illum 0 128 | anim 0.0833333 0.0 129 | Ns 0.000000 130 | map_Kd maps/radar.png 131 | 132 | newmtl white_[rods] 133 | Ka 0.200000 0.200000 0.200000 134 | Kd 1.000000 1.000000 1.000000 135 | Ks 1.000000 1.000000 1.000000 136 | Tr 1.000000 137 | illum 0 138 | Ns 0.000000 139 | map_Kd maps/rodsCompleteMap.png 140 | 141 | newmtl orig_panels_[panel] 142 | Ka 0.200000 0.200000 0.200000 143 | Kd 1.000000 1.000000 1.000000 144 | Ks 1.000000 1.000000 1.000000 145 | Tr 1.000000 146 | illum 0 147 | Ns 0.000000 148 | map_Kd maps/panelCompleteMap.png 149 | -------------------------------------------------------------------------------- /pi3d/examples/models/Raspi256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/Raspi256x256.png -------------------------------------------------------------------------------- /pi3d/examples/models/biplane.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'biplane.blend' 2 | # Material Count: 1 3 | newmtl Material.001_biplane1.jpg 4 | Ns 96.078431 5 | Ka 0.000000 0.000000 0.000000 6 | Kd 0.640000 0.640000 0.640000 7 | Ks 0.500000 0.500000 0.500000 8 | Ni 1.000000 9 | d 1.000000 10 | illum 2 11 | map_Kd biplane1.jpg 12 | 13 | 14 | -------------------------------------------------------------------------------- /pi3d/examples/models/biplane1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/biplane1.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/earthskybox.mtl: -------------------------------------------------------------------------------- 1 | # 2 | # Wavefront material file 3 | # Converted by Meshlab Group 4 | # 5 | 6 | newmtl material_0 7 | Ka 0.200000 0.200000 0.200000 8 | Kd 1.000000 1.000000 1.000000 9 | Ks 1.000000 1.000000 1.000000 10 | Ke 1.1 1.1 1.1 11 | Tr 1.000000 12 | illum 1 13 | Ns 0.000000 14 | map_Kd maps/sbox_left512.png 15 | 16 | newmtl material_1 17 | Ka 0.200000 0.200000 0.200000 18 | Kd 1.000000 1.000000 1.000000 19 | Ks 1.000000 1.000000 1.000000 20 | Ke 1.1 1.1 1.1 21 | Tr 1.000000 22 | illum 1 23 | Ns 0.000000 24 | map_Kd maps/sbox_front512.png 25 | 26 | newmtl material_2 27 | Ka 0.200000 0.200000 0.200000 28 | Kd 1.000000 1.000000 1.000000 29 | Ks 1.000000 1.000000 1.000000 30 | Ke 1.1 1.1 1.1 31 | Tr 1.000000 32 | illum 1 33 | Ns 0.000000 34 | map_Kd maps/sbox_back512.png 35 | 36 | newmtl material_3 37 | Ka 0.200000 0.200000 0.200000 38 | Kd 1.000000 1.000000 1.000000 39 | Ks 1.000000 1.000000 1.000000 40 | Ke 1.1 1.1 1.1 41 | Tr 1.000000 42 | illum 1 43 | Ns 0.000000 44 | map_Kd maps/sbox_right512.png 45 | 46 | newmtl material_4 47 | Ka 0.200000 0.200000 0.200000 48 | Kd 1.000000 1.000000 1.000000 49 | Ks 1.000000 1.000000 1.000000 50 | Ke 1.1 1.1 1.1 51 | Tr 1.000000 52 | illum 1 53 | Ns 0.000000 54 | map_Kd maps/sbox_top512.png 55 | 56 | newmtl material_5 57 | Ka 0.200000 0.200000 0.200000 58 | Kd 1.000000 1.000000 1.000000 59 | Ks 1.000000 1.000000 1.000000 60 | Ke 1.1 1.1 1.1 61 | Tr 1.000000 62 | illum 1 63 | Ns 0.000000 64 | map_Kd maps/sbox_bottom512.png 65 | 66 | -------------------------------------------------------------------------------- /pi3d/examples/models/earthskybox.obj: -------------------------------------------------------------------------------- 1 | #### 2 | # 3 | # OBJ File Generated by Meshlab 4 | # 5 | #### 6 | # Object earthskybox.obj 7 | # 8 | # Vertices: 24 9 | # Faces: 12 10 | # 11 | #### 12 | mtllib earthskybox.mtl 13 | 14 | v -500.499969 -500.500000 -500.499969 15 | v 500.500031 -500.500000 -500.499969 16 | v -500.499969 500.500000 -500.499969 17 | v 500.500031 500.500000 -500.499969 18 | v 500.500031 -500.500000 500.500031 19 | v 500.500031 -500.500000 -500.499969 20 | v 500.500031 500.500000 500.500031 21 | v 500.500031 500.500000 -500.499969 22 | v -500.499969 -500.500000 500.500031 23 | v -500.499969 -500.500000 -500.499969 24 | v -500.499969 500.500000 500.500031 25 | v -500.499969 500.500000 -500.499969 26 | v -500.499969 -500.500000 500.500031 27 | v 500.500031 -500.500000 500.500031 28 | v -500.499969 500.500000 500.500031 29 | v 500.500031 500.500000 500.500031 30 | v -500.499969 500.500000 500.500031 31 | v 500.500031 500.500000 500.500031 32 | v -500.499969 500.500000 -500.499969 33 | v 500.500031 500.500000 -500.499969 34 | v -500.499969 -500.500000 500.500031 35 | v 500.500031 -500.500000 500.500031 36 | v -500.499969 -500.500000 -500.499969 37 | v 500.500031 -500.500000 -500.499969 38 | # 24 vertices, 0 vertices normals 39 | 40 | 41 | usemtl material_0 42 | vt 0.000500 0.000500 43 | vt 0.999500 0.000500 44 | vt 0.000500 0.999500 45 | f 1/1 2/2 3/3 46 | vt 0.999500 0.999500 47 | f 4/4 3/3 2/2 48 | 49 | usemtl material_1 50 | f 6/1 5/2 8/3 51 | f 7/4 8/3 5/2 52 | 53 | usemtl material_2 54 | f 9/1 10/2 11/3 55 | f 12/4 11/3 10/2 56 | 57 | usemtl material_3 58 | f 14/1 13/2 16/3 59 | f 15/4 16/3 13/2 60 | 61 | usemtl material_4 62 | vt 0.999500 0.000500 63 | vt 0.000500 0.000500 64 | f 18/5 17/4 20/6 65 | vt 0.000500 0.999500 66 | f 19/7 20/6 17/4 67 | 68 | usemtl material_5 69 | vt 0.000499 0.000500 70 | vt 0.999500 0.000499 71 | vt 0.000500 0.999500 72 | f 23/8 21/9 24/10 73 | f 22/4 24/10 21/9 74 | # 12 faces, 10 coords texture 75 | 76 | # End of File 77 | -------------------------------------------------------------------------------- /pi3d/examples/models/iss.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 27 3 | 4 | newmtl anisotropic1SG 5 | Ns 94.117647 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.320000 0.320000 0.320000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd Raspi256x256.png 14 | 15 | newmtl anisotropic1SG_leeds_raspberry_jam02c.png 16 | Ns 94.117647 17 | Ka 1.000000 1.000000 1.000000 18 | Kd 0.320000 0.320000 0.320000 19 | Ks 0.500000 0.500000 0.500000 20 | Ke 0.000000 0.000000 0.000000 21 | Ni 1.000000 22 | d 1.000000 23 | illum 2 24 | map_Kd leeds_raspberry_jam02c.png 25 | 26 | newmtl apollohorns_blin 27 | Ns 94.117647 28 | Ka 1.000000 1.000000 1.000000 29 | Kd 0.320000 0.320000 0.320000 30 | Ks 0.500000 0.500000 0.500000 31 | Ke 0.000000 0.000000 0.000000 32 | Ni 1.000000 33 | d 1.000000 34 | illum 2 35 | map_Kd Raspi256x256.png 36 | 37 | newmtl apollohorns_blin_leeds_raspberry_jam02c.png 38 | Ns 94.117647 39 | Ka 1.000000 1.000000 1.000000 40 | Kd 0.320000 0.320000 0.320000 41 | Ks 0.500000 0.500000 0.500000 42 | Ke 0.000000 0.000000 0.000000 43 | Ni 1.000000 44 | d 1.000000 45 | illum 2 46 | map_Kd leeds_raspberry_jam02c.png 47 | 48 | newmtl bendedtruss_blin 49 | Ns 94.117647 50 | Ka 1.000000 1.000000 1.000000 51 | Kd 0.320000 0.320000 0.320000 52 | Ks 0.500000 0.500000 0.500000 53 | Ke 0.000000 0.000000 0.000000 54 | Ni 1.000000 55 | d 1.000000 56 | illum 2 57 | map_Kd leeds_raspberry_jam02c.png 58 | 59 | newmtl blinn1SG 60 | Ns 94.117647 61 | Ka 1.000000 1.000000 1.000000 62 | Kd 0.320000 0.320000 0.320000 63 | Ks 0.500000 0.500000 0.500000 64 | Ke 0.000000 0.000000 0.000000 65 | Ni 1.000000 66 | d 1.000000 67 | illum 2 68 | map_Kd Raspi256x256.png 69 | 70 | newmtl blinn1SG_leeds_raspberry_jam02c.png 71 | Ns 94.117647 72 | Ka 1.000000 1.000000 1.000000 73 | Kd 0.320000 0.320000 0.320000 74 | Ks 0.500000 0.500000 0.500000 75 | Ke 0.000000 0.000000 0.000000 76 | Ni 1.000000 77 | d 1.000000 78 | illum 2 79 | map_Kd leeds_raspberry_jam02c.png 80 | 81 | newmtl blinn3SG 82 | Ns 94.117647 83 | Ka 1.000000 1.000000 1.000000 84 | Kd 0.320000 0.320000 0.320000 85 | Ks 0.500000 0.500000 0.500000 86 | Ke 0.000000 0.000000 0.000000 87 | Ni 1.000000 88 | d 1.000000 89 | illum 2 90 | map_Kd Raspi256x256.png 91 | 92 | newmtl blinn3SG_leeds_raspberry_jam02c.png 93 | Ns 94.117647 94 | Ka 1.000000 1.000000 1.000000 95 | Kd 0.320000 0.320000 0.320000 96 | Ks 0.500000 0.500000 0.500000 97 | Ke 0.000000 0.000000 0.000000 98 | Ni 1.000000 99 | d 1.000000 100 | illum 2 101 | map_Kd leeds_raspberry_jam02c.png 102 | 103 | newmtl blinn4SG 104 | Ns 94.117647 105 | Ka 1.000000 1.000000 1.000000 106 | Kd 0.320000 0.320000 0.320000 107 | Ks 0.500000 0.500000 0.500000 108 | Ke 0.000000 0.000000 0.000000 109 | Ni 1.000000 110 | d 1.000000 111 | illum 2 112 | map_Kd leeds_raspberry_jam02c.png 113 | 114 | newmtl blinn5SG 115 | Ns 94.117647 116 | Ka 1.000000 1.000000 1.000000 117 | Kd 0.320000 0.320000 0.320000 118 | Ks 0.500000 0.500000 0.500000 119 | Ke 0.000000 0.000000 0.000000 120 | Ni 1.000000 121 | d 1.000000 122 | illum 2 123 | map_Kd leeds_raspberry_jam02c.png 124 | 125 | newmtl blinn6SG 126 | Ns 94.117647 127 | Ka 1.000000 1.000000 1.000000 128 | Kd 0.320000 0.320000 0.320000 129 | Ks 0.500000 0.500000 0.500000 130 | Ke 0.000000 0.000000 0.000000 131 | Ni 1.000000 132 | d 1.000000 133 | illum 2 134 | map_Kd leeds_raspberry_jam02c.png 135 | 136 | newmtl blinn7SG 137 | Ns 94.117647 138 | Ka 1.000000 1.000000 1.000000 139 | Kd 0.320000 0.320000 0.320000 140 | Ks 0.500000 0.500000 0.500000 141 | Ke 0.000000 0.000000 0.000000 142 | Ni 1.000000 143 | d 1.000000 144 | illum 2 145 | map_Kd leeds_raspberry_jam02c.png 146 | 147 | newmtl initialShadingGr 148 | Ns 94.117647 149 | Ka 1.000000 1.000000 1.000000 150 | Kd 0.320000 0.320000 0.320000 151 | Ks 0.500000 0.500000 0.500000 152 | Ke 0.000000 0.000000 0.000000 153 | Ni 1.000000 154 | d 1.000000 155 | illum 2 156 | map_Kd Raspi256x256.png 157 | 158 | newmtl initialShadingGr_leeds_raspberry_jam02c.png 159 | Ns 94.117647 160 | Ka 1.000000 1.000000 1.000000 161 | Kd 0.320000 0.320000 0.320000 162 | Ks 0.500000 0.500000 0.500000 163 | Ke 0.000000 0.000000 0.000000 164 | Ni 1.000000 165 | d 1.000000 166 | illum 2 167 | map_Kd leeds_raspberry_jam02c.png 168 | 169 | newmtl lambert2SG 170 | Ns 94.117647 171 | Ka 1.000000 1.000000 1.000000 172 | Kd 0.320000 0.320000 0.320000 173 | Ks 0.500000 0.500000 0.500000 174 | Ke 0.000000 0.000000 0.000000 175 | Ni 1.000000 176 | d 1.000000 177 | illum 2 178 | map_Kd leeds_raspberry_jam02c.png 179 | 180 | newmtl lambert3SG 181 | Ns 94.117647 182 | Ka 1.000000 1.000000 1.000000 183 | Kd 0.320000 0.320000 0.320000 184 | Ks 0.500000 0.500000 0.500000 185 | Ke 0.000000 0.000000 0.000000 186 | Ni 1.000000 187 | d 1.000000 188 | illum 2 189 | map_Kd Raspi256x256.png 190 | 191 | newmtl lambert3SG_leeds_raspberry_jam02c.png 192 | Ns 94.117647 193 | Ka 1.000000 1.000000 1.000000 194 | Kd 0.320000 0.320000 0.320000 195 | Ks 0.500000 0.500000 0.500000 196 | Ke 0.000000 0.000000 0.000000 197 | Ni 1.000000 198 | d 1.000000 199 | illum 2 200 | map_Kd leeds_raspberry_jam02c.png 201 | 202 | newmtl lambert4SG 203 | Ns 94.117647 204 | Ka 1.000000 1.000000 1.000000 205 | Kd 0.320000 0.320000 0.320000 206 | Ks 0.500000 0.500000 0.500000 207 | Ke 0.000000 0.000000 0.000000 208 | Ni 1.000000 209 | d 1.000000 210 | illum 2 211 | map_Kd Raspi256x256.png 212 | 213 | newmtl lambert4SG_leeds_raspberry_jam02c.png 214 | Ns 94.117647 215 | Ka 1.000000 1.000000 1.000000 216 | Kd 0.320000 0.320000 0.320000 217 | Ks 0.500000 0.500000 0.500000 218 | Ke 0.000000 0.000000 0.000000 219 | Ni 1.000000 220 | d 1.000000 221 | illum 2 222 | map_Kd leeds_raspberry_jam02c.png 223 | 224 | newmtl lambert6SG 225 | Ns 94.117647 226 | Ka 1.000000 1.000000 1.000000 227 | Kd 0.320000 0.320000 0.320000 228 | Ks 0.500000 0.500000 0.500000 229 | Ke 0.000000 0.000000 0.000000 230 | Ni 1.000000 231 | d 1.000000 232 | illum 2 233 | map_Kd Raspi256x256.png 234 | 235 | newmtl lambert6SG_leeds_raspberry_jam02c.png 236 | Ns 94.117647 237 | Ka 1.000000 1.000000 1.000000 238 | Kd 0.320000 0.320000 0.320000 239 | Ks 0.500000 0.500000 0.500000 240 | Ke 0.000000 0.000000 0.000000 241 | Ni 1.000000 242 | d 1.000000 243 | illum 2 244 | map_Kd leeds_raspberry_jam02c.png 245 | 246 | newmtl lambert7SG 247 | Ns 94.117647 248 | Ka 1.000000 1.000000 1.000000 249 | Kd 0.320000 0.320000 0.320000 250 | Ks 0.500000 0.500000 0.500000 251 | Ke 0.000000 0.000000 0.000000 252 | Ni 1.000000 253 | d 1.000000 254 | illum 2 255 | map_Kd Raspi256x256.png 256 | 257 | newmtl soyuz_blinn2SG 258 | Ns 94.117647 259 | Ka 1.000000 1.000000 1.000000 260 | Kd 0.320000 0.320000 0.320000 261 | Ks 0.500000 0.500000 0.500000 262 | Ke 0.000000 0.000000 0.000000 263 | Ni 1.000000 264 | d 1.000000 265 | illum 2 266 | map_Kd leeds_raspberry_jam02c.png 267 | 268 | newmtl soyuz_blinn3SG 269 | Ns 94.117647 270 | Ka 1.000000 1.000000 1.000000 271 | Kd 0.320000 0.320000 0.320000 272 | Ks 0.500000 0.500000 0.500000 273 | Ke 0.000000 0.000000 0.000000 274 | Ni 1.000000 275 | d 1.000000 276 | illum 2 277 | map_Kd Raspi256x256.png 278 | 279 | newmtl soyuz_blinn3SG_leeds_raspberry_jam02c.png 280 | Ns 94.117647 281 | Ka 1.000000 1.000000 1.000000 282 | Kd 0.320000 0.320000 0.320000 283 | Ks 0.500000 0.500000 0.500000 284 | Ke 0.000000 0.000000 0.000000 285 | Ni 1.000000 286 | d 1.000000 287 | illum 2 288 | map_Kd leeds_raspberry_jam02c.png 289 | 290 | newmtl soyuz_blinn4SG 291 | Ns 94.117647 292 | Ka 1.000000 1.000000 1.000000 293 | Kd 0.320000 0.320000 0.320000 294 | Ks 0.500000 0.500000 0.500000 295 | Ke 0.000000 0.000000 0.000000 296 | Ni 1.000000 297 | d 1.000000 298 | illum 2 299 | map_Kd leeds_raspberry_jam02c.png 300 | -------------------------------------------------------------------------------- /pi3d/examples/models/leeds_raspberry_jam02c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/leeds_raspberry_jam02c.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/ChevronsCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/ChevronsCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/MedMon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/MedMon1.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/ashphalt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/ashphalt.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/barriersCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/barriersCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/bluealum.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/bluealum.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/bluealumCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/bluealumCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/blueglow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/blueglow.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/bodyCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/bodyCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/fx3_Panels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/fx3_Panels.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/panelCompleteMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/panelCompleteMap.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/radar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/radar.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/red.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/rodsCompleteMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/rodsCompleteMap.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_back.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_bottom.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_front.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_left.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_right.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/sbox_512_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/sbox_512_top.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/stripsCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/stripsCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/walkplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/walkplate.png -------------------------------------------------------------------------------- /pi3d/examples/models/maps/walkwaysCompleteMap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/walkwaysCompleteMap.jpg -------------------------------------------------------------------------------- /pi3d/examples/models/maps/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/models/maps/white.png -------------------------------------------------------------------------------- /pi3d/examples/models/pi3d.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'raspberry.blend' 2 | # Material Count: 8 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | 12 | newmtl blue 13 | Ns 225.000000 14 | Ka 1.000000 1.000000 1.000000 15 | Kd 0.034340 0.061246 0.799103 16 | Ks 0.500000 0.500000 0.500000 17 | Ke 0.0 0.0 0.0 18 | Ni 1.450000 19 | d 1.000000 20 | illum 2 21 | 22 | newmtl body 23 | Ns 225.000000 24 | Ka 1.000000 1.000000 1.000000 25 | Kd 0.008023 0.008023 0.008023 26 | Ks 0.500000 0.500000 0.500000 27 | Ke 0.0 0.0 0.0 28 | Ni 1.450000 29 | d 1.000000 30 | illum 2 31 | 32 | newmtl green 33 | Ns 225.000000 34 | Ka 1.000000 1.000000 1.000000 35 | Kd 0.003347 0.309469 0.010330 36 | Ks 0.500000 0.500000 0.500000 37 | Ke 0.0 0.0 0.0 38 | Ni 1.450000 39 | d 1.000000 40 | illum 2 41 | 42 | newmtl leaves 43 | Ns 225.000000 44 | Ka 1.000000 1.000000 1.000000 45 | Kd 0.012286 0.109462 0.006049 46 | Ks 0.500000 0.500000 0.500000 47 | Ke 0.0 0.0 0.0 48 | Ni 1.450000 49 | d 1.000000 50 | illum 2 51 | 52 | newmtl pips 53 | Ns 225.000000 54 | Ka 1.000000 1.000000 1.000000 55 | Kd 0.539480 0.022174 0.033105 56 | Ks 0.500000 0.500000 0.500000 57 | Ke 0.0 0.0 0.0 58 | Ni 1.450000 59 | d 1.000000 60 | illum 2 61 | 62 | newmtl red 63 | Ns 225.000000 64 | Ka 1.000000 1.000000 1.000000 65 | Kd 0.799103 0.000000 0.006512 66 | Ks 0.500000 0.500000 0.500000 67 | Ke 0.0 0.0 0.0 68 | Ni 1.450000 69 | d 1.000000 70 | illum 2 71 | 72 | newmtl yellow 73 | Ns 225.000000 74 | Ka 1.000000 1.000000 1.000000 75 | Kd 0.799103 0.391572 0.004025 76 | Ks 0.500000 0.500000 0.500000 77 | Ke 0.0 0.0 0.0 78 | Ni 1.450000 79 | d 1.000000 80 | illum 2 81 | -------------------------------------------------------------------------------- /pi3d/examples/models/pi3d_old.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'pi3d.blend' 2 | # Material Count: 7 3 | newmtl Material.001_pi3d.jpg 4 | Ns 96.078431 5 | Ka 0.000000 0.000000 0.000000 6 | Kd 0.800000 0.676835 0.000000 7 | Ks 0.005677 0.500000 0.416809 8 | Ni 1.000000 9 | d 1.000000 10 | illum 2 11 | map_Kd pi3d.jpg 12 | 13 | 14 | newmtl Material.002_pi3d.jpg 15 | Ns 96.078431 16 | Ka 0.000000 0.000000 0.000000 17 | Kd 0.800000 0.000000 0.000000 18 | Ks 0.003166 0.500000 0.403850 19 | Ni 1.000000 20 | d 1.000000 21 | illum 2 22 | map_Kd pi3d.jpg 23 | 24 | 25 | newmtl Material.003_pi3d.jpg 26 | Ns 96.078431 27 | Ka 0.000000 0.000000 0.000000 28 | Kd 0.078331 0.626651 0.087035 29 | Ks 0.000000 0.500000 0.426184 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | map_Kd pi3d.jpg 34 | 35 | 36 | newmtl Material.004_pi3d.jpg 37 | Ns 96.078431 38 | Ka 0.000000 0.000000 0.000000 39 | Kd 0.081481 0.081481 0.836574 40 | Ks 0.023671 0.500000 0.448963 41 | Ni 1.000000 42 | d 1.000000 43 | illum 2 44 | map_Kd pi3d.jpg 45 | 46 | 47 | newmtl Material.005_pi3d.jpg 48 | Ns 96.078431 49 | Ka 0.000000 0.000000 0.000000 50 | Kd 0.020314 0.020314 0.020314 51 | Ks 0.500000 0.500000 0.500000 52 | Ni 1.000000 53 | d 1.000000 54 | illum 2 55 | map_Kd pi3d.jpg 56 | 57 | 58 | newmtl Material.006_pi3d.jpg 59 | Ns 96.078431 60 | Ka 0.000000 0.000000 0.000000 61 | Kd 0.800000 0.000000 0.000000 62 | Ks 0.500000 0.500000 0.500000 63 | Ni 1.000000 64 | d 1.000000 65 | illum 2 66 | map_Kd pi3d.jpg 67 | 68 | 69 | newmtl Material.007_pi3d.jpg 70 | Ns 96.078431 71 | Ka 0.000000 0.000000 0.000000 72 | Kd 0.014302 0.192450 0.000000 73 | Ks 0.038264 0.500000 0.461755 74 | Ni 1.000000 75 | d 1.000000 76 | illum 2 77 | map_Kd pi3d.jpg 78 | 79 | 80 | -------------------------------------------------------------------------------- /pi3d/examples/models/rust_pi3d.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'pi3R.blend' 2 | # Material Count: 6 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | 12 | newmtl black_rust 13 | Ns 225.000000 14 | Ka 1.000000 1.000000 1.000000 15 | Kd 0.009134 0.008023 0.007499 16 | Ks 0.500000 0.500000 0.500000 17 | Ke 0.0 0.0 0.0 18 | Ni 1.450000 19 | d 1.000000 20 | illum 3 21 | 22 | newmtl blue 23 | Ns 225.000000 24 | Ka 1.000000 1.000000 1.000000 25 | Kd 0.034340 0.061246 0.799103 26 | Ks 0.500000 0.500000 0.500000 27 | Ke 0.0 0.0 0.0 28 | Ni 1.450000 29 | d 1.000000 30 | illum 2 31 | 32 | newmtl green 33 | Ns 225.000000 34 | Ka 1.000000 1.000000 1.000000 35 | Kd 0.003347 0.309469 0.010330 36 | Ks 0.500000 0.500000 0.500000 37 | Ke 0.0 0.0 0.0 38 | Ni 1.450000 39 | d 1.000000 40 | illum 2 41 | 42 | newmtl red 43 | Ns 225.000000 44 | Ka 1.000000 1.000000 1.000000 45 | Kd 0.799103 0.000000 0.006512 46 | Ks 0.500000 0.500000 0.500000 47 | Ke 0.0 0.0 0.0 48 | Ni 1.450000 49 | d 1.000000 50 | illum 2 51 | 52 | newmtl yellow 53 | Ns 225.000000 54 | Ka 1.000000 1.000000 1.000000 55 | Kd 0.799103 0.391572 0.004025 56 | Ks 0.500000 0.500000 0.500000 57 | Ke 0.0 0.0 0.0 58 | Ni 1.450000 59 | d 1.000000 60 | illum 2 61 | -------------------------------------------------------------------------------- /pi3d/examples/picture_frame.rs: -------------------------------------------------------------------------------- 1 | extern crate pi3d; 2 | extern crate rand; 3 | extern crate sdl2; 4 | 5 | use rand::seq::SliceRandom; 6 | use rand::thread_rng; 7 | use std::fs; 8 | use std::path::Path; 9 | use std::time::{Duration, Instant}; 10 | //use std::thread::sleep; 11 | 12 | const IMG_EXT: [&str; 6] = ["jpg", "JPG", "jpeg", "JPEG", "png", "PNG"]; 13 | const FILE_DIR: &str = "./"; 14 | //const FILE_DIR: &str = "/home/patrick/Pictures"; // or absolute path 15 | 16 | // recursive function to build list of image files. Pass ref to vec to build in place 17 | fn get_files(dir: &Path, file_list: &mut Vec) { 18 | for entry in fs::read_dir(dir).unwrap() { 19 | // will panic if dir is not a Path 20 | match entry { 21 | Ok(dir_entry) => { 22 | let path = dir_entry.path(); 23 | if path.is_dir() { 24 | get_files(&path, file_list); // recurse into dir 25 | } else { 26 | // it's a file, check if image TODO exif dates and rotation 27 | let path_str = path.to_str().unwrap().to_string(); 28 | let extension = path_str.split(".").last().unwrap(); 29 | if IMG_EXT.iter().any(|&x| x == extension) { 30 | file_list.push(path_str); 31 | } 32 | } 33 | } 34 | _ => { 35 | println!("odd entry in directory, permission?"); 36 | } 37 | } 38 | } 39 | } 40 | 41 | fn main() { 42 | let time_delay = Duration::new(10, 0); // duration per slide in (seconds, nanoseconds) 43 | let fade_time = Duration::new(5, 0); 44 | 45 | // initially set up display, shader, camera, texture and shapes 46 | let mut display = 47 | pi3d::display::create("picture_frame ESC to quit", 100.0, 100.0, "GL", 2, 1).unwrap(); 48 | display.set_fullscreen(true); 49 | display.set_background(&[0.2, 0.2, 0.2, 1.0]); 50 | display.set_target_fps(30.0); 51 | let shader = pi3d::shader::Program::from_res("shaders/blend_new").unwrap(); 52 | let mut camera = pi3d::camera::create(&display); 53 | camera.set_3d(false); // make it a 2D shader 54 | let (w, h) = display.get_size(); 55 | let mut slide = pi3d::shapes::plane::create(camera.reference(), w as f32, h as f32); // fullscreen 56 | slide.set_draw_details(&shader, &vec![], 1.0, 1.0, 1.0, 1.0, 1.0); 57 | //slide.position_z(5.0); 58 | 59 | // pi3d has a resources function that checks if path has root 60 | let file_path = pi3d::util::resources::resource_name_to_path(FILE_DIR); 61 | let mut file_list: Vec = vec![]; 62 | get_files(&file_path, &mut file_list); 63 | let mut rng = thread_rng(); 64 | file_list.shuffle(&mut rng); 65 | 66 | let mut sbg: Option = None; //Options used to cater for bad image files later 67 | let mut sfg: Option = None; 68 | 69 | let mut last_tm = Instant::now().checked_sub(time_delay).unwrap(); 70 | let mut pic_num = 0usize; 71 | // draw in a loop 72 | while display.loop_running() { 73 | // default sdl2 check for ESC or click cross 74 | let delta_tm = last_tm.elapsed(); 75 | if delta_tm.as_secs() > time_delay.as_secs() { 76 | let mut loop_i = 0; 77 | loop { 78 | loop_i += 1; 79 | if sfg.is_some() { 80 | sbg = sfg.take(); // leave None in its place 81 | } 82 | if !sfg.is_some() { 83 | // as could have been set to None 84 | let mut tex = pi3d::texture::create_from_file(file_list[pic_num].as_str()); 85 | tex.set_mirrored_repeat(true); 86 | sfg = Some(tex); 87 | pic_num += 1; 88 | if pic_num >= file_list.len() { 89 | pic_num = 0; 90 | } 91 | } 92 | if (sfg.is_some() && sbg.is_some()) || loop_i > 5 { 93 | break; 94 | } 95 | } 96 | let sfg_tex = sfg.expect("missing f_gnd image"); // unwrap them here to use contained info 97 | let sbg_tex = sbg.expect("missing bk_gnd image"); 98 | slide.set_textures(&vec![sfg_tex.id, sbg_tex.id]); 99 | let w = sfg_tex.width; 100 | let h = sfg_tex.height; 101 | sfg = Some(sfg_tex); // wrapped up again for next loop 102 | sbg = Some(sbg_tex); 103 | slide.unif[[15, 0]] = slide.unif[[14, 0]]; // copy forgrnd to bkgrnd 104 | slide.unif[[15, 1]] = slide.unif[[14, 1]]; 105 | slide.unif[[17, 0]] = slide.unif[[16, 0]]; 106 | slide.unif[[17, 1]] = slide.unif[[16, 1]]; 107 | let wh_rat = (display.width * h as f32) / (display.height * w as f32); 108 | let (ix0, ix1) = if wh_rat > 1.0 { (0, 1) } else { (1, 0) }; 109 | slide.unif[[14, ix0]] = wh_rat; 110 | slide.unif[[14, ix1]] = 1.0; 111 | slide.unif[[16, ix0]] = (wh_rat - 1.0) * 0.5; 112 | slide.unif[[16, ix1]] = 0.0; 113 | 114 | slide.unif[[14, 2]] = 0.0; 115 | slide.unif[[15, 2]] = 0.5; 116 | last_tm = Instant::now(); 117 | } else { 118 | let a: f32 = delta_tm.as_millis() as f32 / fade_time.as_millis() as f32; 119 | slide.unif[[14, 2]] = if a < 1.0 { a } else { 1.0 }; 120 | } 121 | slide.draw(); 122 | //TODO sleep while nothing's changing? 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /pi3d/examples/shader_in_src.rs: -------------------------------------------------------------------------------- 1 | extern crate gl; 2 | extern crate pi3d; 3 | extern crate sdl2; 4 | 5 | use std::ffi::CString; 6 | 7 | fn main() { 8 | // initially set up display, shader, camera, texture and shapes 9 | let mut display = pi3d::display::create( 10 | "shader source in code ESC to quit", 11 | 800.0, 12 | 500.0, 13 | "GLES", 14 | 3, 15 | 0, 16 | ) 17 | .unwrap(); 18 | display.set_background(&[0.4, 0.5, 0.4, 1.0]); 19 | display.set_opacity(0.9); 20 | let v_shader = pi3d::shader::Shader::from_source( 21 | &CString::new( 22 | "#version 300 es 23 | precision mediump float; 24 | 25 | layout(location = 0) in vec3 vertex; /// called vertex in pi3d 26 | 27 | void main() 28 | { 29 | gl_Position = vec4(vertex, 1.0); 30 | }", 31 | ) 32 | .unwrap(), 33 | gl::VERTEX_SHADER, 34 | ) 35 | .unwrap(); 36 | /* 37 | // simple setup from github.com/Blakkis/GLSL_Python 38 | let f_shader = pi3d::shader::Shader::from_source(&CString::new( 39 | "#version 300 es 40 | precision mediump float; 41 | #define fragCoord gl_FragCoord.xy 42 | //uniform vec2 iMouse; 43 | //uniform float iTime; /// unif[19].z 44 | //uniform vec2 iResolution; /// unif[19].xy 45 | uniform vec3 unif[20]; 46 | out vec4 fragColor; 47 | void main() 48 | { 49 | vec2 iResolution = unif[19].xy; 50 | float iTime = unif[19][2]; 51 | // Set origin to center of the screen 52 | vec2 uv = fragCoord/iResolution.xy * 2.0 - 1.0; 53 | // Fix aspect ratio 54 | uv.x *= iResolution.x / iResolution.y; 55 | // Time varying pixel color (Copied from ShaderToy default scene) 56 | vec3 color = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0.0, 2.0, 4.0)); 57 | fragColor = vec4(color, 1.0); 58 | //fragColor = vec4(1.0, 1.0, 0.5, 1.0); 59 | }").unwrap(), gl::FRAGMENT_SHADER).unwrap(); 60 | */ 61 | // raymarch_mod setup from github.com/Blakkis/GLSL_Python 62 | let f_shader = pi3d::shader::Shader::from_source( 63 | &CString::new( 64 | "#version 300 es 65 | precision mediump float; 66 | #define fragCoord gl_FragCoord.xy 67 | //uniform vec2 iMouse; /// unif[18].xy 68 | //uniform float iTime; /// unif[19].z 69 | //uniform vec2 iResolution; /// unif[19].xy 70 | uniform vec3 unif[20]; 71 | out vec4 fragColor; 72 | 73 | float sdSphere(vec3 p, float r) { 74 | return length(p) - r; 75 | } 76 | 77 | float map_the_world(in vec3 pos) { 78 | float iTime = unif[19].z; 79 | float displacement = sin(abs(4.0 * cos(iTime)) * pos.x) * 80 | sin(abs(4.0 * sin(iTime)) * pos.y) * 81 | sin(4.0 * pos.z) * 82 | (0.1 + abs(0.1 * sin(iTime * 2.0))); 83 | float sphere_0 = sdSphere(pos, 2.5) + displacement; 84 | return sphere_0; 85 | } 86 | 87 | vec3 calculate_normal(in vec3 pos) { 88 | const vec3 small_step = vec3(0.001, 0.0, 0.0); 89 | float gradient_x = map_the_world(pos + small_step.xyy) - map_the_world(pos - small_step.xyy); 90 | float gradient_y = map_the_world(pos + small_step.yxy) - map_the_world(pos - small_step.yxy); 91 | float gradient_z = map_the_world(pos + small_step.yyx) - map_the_world(pos - small_step.yyx); 92 | vec3 normal = vec3(gradient_x, gradient_y, gradient_z); 93 | return normalize(normal); 94 | } 95 | 96 | vec3 ray_march(in vec3 ro, in vec3 rd) { 97 | vec2 iMouse = unif[18].xy; 98 | float total_distance_traveled = 0.0; 99 | const int NUMBER_OF_STEPS = 128; 100 | const float MINIMUM_HIT_DISTANCE = 0.001; 101 | const float MAXIMUM_TRACE_DISTANCE = 512.0; 102 | const float AMBIENT = 0.2; 103 | for (int i = 0; i < NUMBER_OF_STEPS; ++i) 104 | { 105 | vec3 current_position = ro + total_distance_traveled * rd; 106 | float distance_to_closest = map_the_world(current_position); 107 | if (distance_to_closest < MINIMUM_HIT_DISTANCE) 108 | { 109 | vec3 normal = calculate_normal(current_position); 110 | vec3 light_position = vec3(-iMouse.x, iMouse.y, 4.0); 111 | vec3 direction_to_light = normalize(current_position - light_position); 112 | float diffuse_intensity = max(AMBIENT, pow(dot(normal, direction_to_light), 16.0)); 113 | return vec3(1.0, 0.0, 0.0) * diffuse_intensity; 114 | } 115 | if (total_distance_traveled > MAXIMUM_TRACE_DISTANCE){ 116 | break; 117 | } 118 | total_distance_traveled += distance_to_closest; 119 | } 120 | return vec3(0.0); 121 | } 122 | 123 | void main() { 124 | vec2 iResolution = unif[19].xy; 125 | vec2 uv = fragCoord / iResolution.xy * 2.0 - 1.0; 126 | uv.x *= iResolution.x / iResolution.y; 127 | vec3 camera_position = vec3(0.0, 0.0, -5.0); 128 | vec3 ray_origin = camera_position; 129 | vec3 ray_direction = vec3(uv, 1.0); 130 | vec3 result = ray_march(ray_origin, ray_direction); 131 | fragColor = vec4(result, 1.0); 132 | } 133 | ", 134 | ) 135 | .unwrap(), 136 | gl::FRAGMENT_SHADER, 137 | ) 138 | .unwrap(); 139 | 140 | let shader = pi3d::shader::Program::from_shaders(&[v_shader, f_shader]).unwrap(); 141 | let mut camera = pi3d::camera::create(&display); 142 | camera.set_3d(false); // make it a 2D shader 143 | let (w, h) = display.get_size(); 144 | let mut slide = pi3d::shapes::plane::create(camera.reference(), 0.5 * w as f32, 0.5 * h as f32); // fullscreen 145 | slide.set_draw_details(&shader, &vec![], 1.0, 1.0, 1.0, 1.0, 1.0); 146 | slide.unif[[19, 0]] = w as f32; 147 | slide.unif[[19, 1]] = h as f32; 148 | let mut t: f32 = 0.0; 149 | let mut mx: f32 = 0.0; 150 | let mut my: f32 = 0.0; 151 | // draw in a loop 152 | while display.loop_running() { 153 | // default sdl2 check for ESC or click cross 154 | t += 0.0001; // v. approx time 155 | slide.unif[[19, 2]] = t; 156 | if display.mouse_moved { 157 | my = display.mouse_y as f32; 158 | mx = display.mouse_x as f32; 159 | } 160 | slide.unif[[18, 0]] = 2.0 * mx / w - 1.0; 161 | slide.unif[[18, 1]] = 2.0 * my / h - 1.0; 162 | slide.draw(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/blend_new.fs: -------------------------------------------------------------------------------- 1 | #include std_head_fs.inc 2 | 3 | varying vec2 texcoordoutf; 4 | varying vec2 texcoordoutb; 5 | 6 | //fragcolor 7 | 8 | void main(void) { 9 | vec4 texf = texture2D(tex0, texcoordoutf); 10 | if (texcoordoutf[0] < 0.0 || texcoordoutf[0] > 1.0 || 11 | texcoordoutf[1] < 0.0 || texcoordoutf[1] > 1.0) { 12 | texf.a = unif[15][2]; 13 | } 14 | vec4 texb = texture2D(tex1, texcoordoutb); 15 | if (texcoordoutb[0] < 0.0 || texcoordoutb[0] > 1.0 || 16 | texcoordoutb[1] < 0.0 || texcoordoutf[1] > 1.0) { 17 | texb.a = unif[15][2]; 18 | } 19 | 20 | // blending 21 | float a = unif[14][2]; 22 | 23 | // simple fade ////////////////////////////////////////////////////// 24 | //gl_FragColor = mix(texb, texf, clamp(1.1 * a - 1.0, 0.0, 1.0)); 25 | 26 | // burn ///////////////////////////////////////////////////////////// 27 | float y = 1.0 - smoothstep(a + 0.1, a + 0.3, length(texf.rgb) * 0.5); 28 | gl_FragColor = mix(texb, texf * y, step(1.0, y)); 29 | 30 | // bump ///////////////////////////////////////////////////////////// 31 | //vec4 light = vec4(0.577, 0.577, 0.577, 1.0); 32 | //float ffact = dot(light, texf); 33 | //gl_FragColor = mix(texb * (1.0 + a * (ffact - 1.0)), texf, clamp(2.0 * a - 1.0, 0.0, 1.0)); 34 | } 35 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/blend_new.vs: -------------------------------------------------------------------------------- 1 | #include std_head_vs.inc 2 | 3 | varying vec2 texcoordoutf; 4 | varying vec2 texcoordoutb; 5 | 6 | void main(void) { 7 | texcoordoutf = (texcoord * unif[14].xy - unif[16].xy); 8 | texcoordoutb = (texcoord * unif[15].xy - unif[17].xy); 9 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 10 | dist = gl_Position.z; 11 | gl_PointSize = unib[2][2] / dist; 12 | } -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | varying vec2 texcoordout; 5 | 6 | uniform sampler2D tex0; 7 | uniform vec3 unif[20]; 8 | 9 | //fragcolor 10 | 11 | float TWO_PI = radians(360.0); 12 | float ROOT_3 = sqrt(3.0); 13 | 14 | 15 | vec2 eul(float angle) { 16 | return vec2(cos(angle), sin(angle)); 17 | } 18 | 19 | void main(void) { 20 | float F = unif[16][1]; // borrow R-rot 21 | float F1 = unif[11][0]; // borrow L-n1 22 | float F2 = unif[11][1]; // borrow L-m1 23 | vec2 z = texcoordout * F; 24 | 25 | vec2 uv_coord = (eul(TWO_PI * z.y) + 26 | eul(TWO_PI * (ROOT_3 * z.x - z.y) * F1) + 27 | eul(TWO_PI * (-ROOT_3 * z.x - z.y) * F2)) / 3.0 + 0.5; 28 | /* When F1 = F2 = 0.5 this is approximately as per Farris page 67 with 29 | the modification that rather then everything being divided by 3.0 it is 30 | divided by 6.0 and has 0.5 added this is to scale the uv coordinates to 31 | the mapping used by GLSL (0,0) in the top right corner and (1,1) bottom 32 | left 33 | */ 34 | gl_FragColor = texture2D(tex0, uv_coord); 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec2 texcoord; 6 | 7 | uniform mat4 modelviewmatrix[2]; // 0 model movement in real coords, 1 in camera coords 8 | uniform vec3 unib[4]; 9 | //uniform vec2 umult, vmult => unib[2] 10 | //uniform vec2 u_off, v_off => unib[3] 11 | uniform vec3 unif[20]; // hpe 12 | 13 | varying vec2 texcoordout; 14 | 15 | void main(void) { 16 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 17 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 18 | } 19 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67a.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | varying vec2 texcoordout; 5 | 6 | uniform sampler2D tex0; 7 | uniform vec3 unif[20]; 8 | 9 | //fragcolor 10 | 11 | float TWO_PI = radians(360.0); 12 | float ROOT_3 = sqrt(3.0); 13 | float F3 = 0.5; 14 | float Q_PI = radians(45.0); 15 | 16 | vec2 eul(float angle) { 17 | return vec2(cos(angle), sin(angle)); 18 | } 19 | 20 | void main(void) { 21 | /* This shader is the same as farris_p67 apart from the pattern scaling 22 | z is fixed at 2.0 times the texcoord (which varies 0,0 top left to 1,1 23 | bottom right.) F now varies the amount of color rotation by multiplying with 24 | the x component of z. i.e. none at left and F at right. 25 | 26 | If the rgb vector is rotated about the origin the values will become 27 | negative for much of the time (and default is to clamp to range 0-1). 28 | So the vector from (0.5, 0.5, 0.5) to the rgp point is rotated about an 29 | orthogonal axis to that (i.e. (0, -b', g').dot(r', g', b') == 0) and the result 30 | has (0.5, 0.5, 0.5) added back to it. The result will still fall outside 31 | the 0-1 range occasionally but won't be too bad. 32 | 33 | The 3x3 matrix rot is standard for rotating about an axis 34 | */ 35 | float F = unif[16][1]; // scales the color rotation 36 | float F1 = unif[11][0]; // borrow L-n1 37 | float F2 = unif[11][1]; // borrow L-m1 38 | vec2 z = texcoordout * 2.0; 39 | 40 | vec2 uv_coord = (eul(TWO_PI * z.y) + 41 | eul(TWO_PI * (ROOT_3 * z.x - z.y) * F1) + 42 | eul(TWO_PI * (-ROOT_3 * z.x - z.y) * F2)) / 6.0 + 0.5; 43 | gl_FragColor = texture2D(tex0, uv_coord) - vec4(0.5, 0.5, 0.5, 0.0); //keep alpha 1.0 44 | vec3 ax = normalize(vec3(0.0, gl_FragColor.z, -gl_FragColor.y)); // unit vector along axis 45 | float sa = sin(F * texcoordout.x * Q_PI); 46 | float ca = 1.0 - cos(F * texcoordout.x * Q_PI); 47 | mat3 rot = mat3(1.0 - ca, ax.z * sa, -ax.y * sa, 48 | -ax.y * sa, 1.0 + ca * (ax.y * ax.y - 1.0), ca * ax.y * ax.z, 49 | ax.y * sa, ca * ax.z * ax.y, 1.0 + ca * (ax.z * ax.z - 1.0)); 50 | 51 | gl_FragColor.xyz = rot * gl_FragColor.xyz + vec3(0.5); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67a.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec2 texcoord; 6 | 7 | uniform mat4 modelviewmatrix[2]; // 0 model movement in real coords, 1 in camera coords 8 | uniform vec3 unib[4]; 9 | //uniform vec2 umult, vmult => unib[2] 10 | //uniform vec2 u_off, v_off => unib[3] 11 | uniform vec3 unif[20]; 12 | 13 | varying vec2 texcoordout; 14 | 15 | void main(void) { 16 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 17 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 18 | } 19 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67b.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | varying vec2 texcoordout; 5 | 6 | uniform sampler2D tex0; 7 | uniform vec3 unif[20]; 8 | 9 | //fragcolor 10 | 11 | float TWO_PI = radians(360.0); 12 | float INV_RT3 = inversesqrt(3.0); 13 | 14 | 15 | vec2 eul(float angle) { 16 | return vec2(cos(angle), sin(angle)); 17 | } 18 | 19 | vec2 W(float n, float m, vec2 z) { 20 | return (eul(TWO_PI * (n * z.x + (n + 2.0 * m) * z.y * INV_RT3)) + 21 | eul(TWO_PI * (m * z.x - (2.0 * n + m) * z.y * INV_RT3)) + 22 | eul(TWO_PI * (-(n + m) * z.x + (n - m) * z.y * INV_RT3))) / 3.0; 23 | } 24 | 25 | void main(void) { 26 | float mix_f = smoothstep(0.2, 0.8, texcoordout.x); // linear between 0->1 as x 0.2->0.8 27 | float n1 = mix(unif[11][0], unif[13][2], mix_f); // lerp between left value and right value 28 | float m1 = mix(unif[11][1], unif[14][0], mix_f); 29 | float ar1 = mix(unif[11][2], unif[14][1], mix_f); 30 | float ai1 = mix(unif[12][0], unif[14][2], mix_f); 31 | float n2 = mix(unif[12][1], unif[15][0], mix_f); 32 | float m2 = mix(unif[12][2], unif[15][1], mix_f); 33 | float ar2 = mix(unif[13][0], unif[15][2], mix_f); 34 | float ai2 = mix(unif[13][1], unif[16][0], mix_f); 35 | 36 | vec2 z = texcoordout * 4.0; 37 | /* This shader uses the Hexagonal lattice recipe P6 from Farris p213 38 | it scales z to value fixed above. n, m, a_real and a_imag are taken from 39 | unif as above. There are four Ws n1,m1 -n1,-m1 n2,m2 -n2,-m2 but these 40 | can be added in pairs because of the requirement for a_n,m == a_-n,-m 41 | */ 42 | vec2 w1 = W(n1, m1, z) + W(-n1, -m1, z); 43 | vec2 w2 = W(n2, m2, z) + W(-n2, -m2, z); 44 | vec2 uv_coord = vec2(ar1 * w1.x - ai1 * w1.y + ar2 * w2.x - ai2 * w2.y, 45 | ar1 * w1.y + ai1 * w1.x + ar2 * w2.y + ai2 * w2.x); 46 | /* The right sample texture can be rotated by the passed in unif[16][1] 47 | which is pro-ratad across the width. The rotation is done by simple 48 | 2D rotation matrix as below. (vec2(0.5) adjustment to rotate about centre) 49 | */ 50 | float c_angl = mix_f * unif[16][1]; 51 | mat2 rotn = mat2(cos(c_angl), sin(c_angl), 52 | -sin(c_angl), cos(c_angl)); 53 | gl_FragColor = texture2D(tex0, rotn * (uv_coord - vec2(0.5)) + vec2(0.5)); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67b.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec2 texcoord; 6 | 7 | uniform mat4 modelviewmatrix[2]; // 0 model movement in real coords, 1 in camera coords 8 | uniform vec3 unib[4]; 9 | //uniform vec2 umult, vmult => unib[2] 10 | //uniform vec2 u_off, v_off => unib[3] 11 | uniform vec3 unif[20]; // hpe 12 | 13 | varying vec2 texcoordout; 14 | 15 | void main(void) { 16 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 17 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 18 | } 19 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67b_ES30.fs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | in vec2 texcoordout; 5 | 6 | uniform sampler2D tex0; 7 | uniform vec3 unif[20]; 8 | 9 | out vec4 fragColor; 10 | 11 | float TWO_PI = radians(360.0); 12 | float INV_RT3 = inversesqrt(3.0); 13 | 14 | vec2 eul(float angle) { 15 | return vec2(cos(angle), sin(angle)); 16 | } 17 | 18 | vec2 W(float n, float m, vec2 z) { 19 | return (eul(TWO_PI * (n * z.x + (n + 2.0 * m) * z.y * INV_RT3)) + 20 | eul(TWO_PI * (m * z.x - (2.0 * n + m) * z.y * INV_RT3)) + 21 | eul(TWO_PI * (-(n + m) * z.x + (n - m) * z.y * INV_RT3))) / 3.0; 22 | } 23 | 24 | void main(void) { 25 | float mix_f = smoothstep(0.2, 0.8, texcoordout.x); // linear between 0->1 as x 0.2->0.8 26 | float n1 = mix(unif[11][0], unif[13][2], mix_f); // lerp between left value and right value 27 | float m1 = mix(unif[11][1], unif[14][0], mix_f); 28 | float ar1 = mix(unif[11][2], unif[14][1], mix_f); 29 | float ai1 = mix(unif[12][0], unif[14][2], mix_f); 30 | float n2 = mix(unif[12][1], unif[15][0], mix_f); 31 | float m2 = mix(unif[12][2], unif[15][1], mix_f); 32 | float ar2 = mix(unif[13][0], unif[15][2], mix_f); 33 | float ai2 = mix(unif[13][1], unif[16][0], mix_f); 34 | 35 | vec2 z = texcoordout * 4.0; 36 | /* This shader uses the Hexagonal lattice recipe P6 from Farris p213 37 | it scales z to value fixed above. n, m, a_real and a_imag are taken from 38 | unif as above. There are four Ws n1,m1 -n1,-m1 n2,m2 -n2,-m2 but these 39 | can be added in pairs because of the requirement for a_n,m == a_-n,-m 40 | */ 41 | vec2 w1 = W(n1, m1, z) + W(-n1, -m1, z); 42 | vec2 w2 = W(n2, m2, z) + W(-n2, -m2, z); 43 | vec2 uv_coord = vec2(ar1 * w1.x - ai1 * w1.y + ar2 * w2.x - ai2 * w2.y, 44 | ar1 * w1.y + ai1 * w1.x + ar2 * w2.y + ai2 * w2.x); 45 | /* The right sample texture can be rotated by the passed in unif[16][1] 46 | which is pro-ratad across the width. The rotation is done by simple 47 | 2D rotation matrix as below. (vec2(0.5) adjustment to rotate about centre) 48 | */ 49 | float c_angl = mix_f * unif[16][1]; 50 | mat2 rotn = mat2(cos(c_angl), sin(c_angl), 51 | -sin(c_angl), cos(c_angl)); 52 | fragColor = texture(tex0, rotn * (uv_coord - vec2(0.5)) + vec2(0.5)); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p67b_ES30.vs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | in vec3 vertex; 5 | in vec2 texcoord; 6 | 7 | uniform mat4 modelviewmatrix[2]; // 0 model movement in real coords, 1 in camera coords 8 | uniform vec3 unib[4]; 9 | //uniform vec2 umult, vmult => unib[2] 10 | //uniform vec2 u_off, v_off => unib[3] 11 | uniform vec3 unif[20]; // hpe 12 | 13 | out vec2 texcoordout; 14 | 15 | void main(void) { 16 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 17 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 18 | } 19 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p6_6term.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | varying vec2 texcoordout; 5 | 6 | uniform sampler2D tex0; 7 | uniform vec3 unif[20]; 8 | 9 | //fragcolor 10 | 11 | float TWO_PI = radians(360.0); 12 | float INV_RT3 = inversesqrt(3.0); 13 | 14 | 15 | vec2 eul(float angle) { 16 | return vec2(cos(angle), sin(angle)); 17 | } 18 | 19 | vec2 W(float n, float m, vec2 z) { 20 | return (eul(TWO_PI * (n * z.x + (n + 2.0 * m) * z.y * INV_RT3)) + 21 | eul(TWO_PI * (m * z.x - (2.0 * n + m) * z.y * INV_RT3)) + 22 | eul(TWO_PI * (-(n + m) * z.x + (n - m) * z.y * INV_RT3))) / 3.0; 23 | } 24 | 25 | void main(void) { 26 | float mix_f = smoothstep(0.2, 0.8, texcoordout.x); // linear between 0->1 as x 0.2->0.8 27 | float n1 = mix(unif[11][0], unif[15][0], mix_f); // lerp between left value and right value 28 | float m1 = mix(unif[11][1], unif[15][1], mix_f); 29 | float ar1 = mix(unif[11][2], unif[15][2], mix_f); 30 | float ai1 = mix(unif[12][0], unif[16][0], mix_f); 31 | float n2 = mix(unif[12][1], unif[16][1], mix_f); 32 | float m2 = mix(unif[12][2], unif[16][2], mix_f); 33 | float ar2 = mix(unif[13][0], unif[17][0], mix_f); 34 | float ai2 = mix(unif[13][1], unif[17][1], mix_f); 35 | float n3 = mix(unif[13][2], unif[17][2], mix_f); 36 | float m3 = mix(unif[14][0], unif[18][0], mix_f); 37 | float ar3 = mix(unif[14][1], unif[18][1], mix_f); 38 | float ai3 = mix(unif[14][2], unif[18][2], mix_f); 39 | 40 | vec2 z = texcoordout * 4.0; 41 | /* This shader uses the Hexagonal lattice recipe P6 from Farris p213 42 | it scales z to value fixed above. n, m, a_real and a_imag are taken from 43 | unif as above. There are four Ws n1,m1 -n1,-m1 n2,m2 -n2,-m2 but these 44 | can be added in pairs because of the requirement for a_n,m == a_-n,-m 45 | */ 46 | vec2 w1 = W(n1, m1, z) + W(-n1, -m1, z); 47 | vec2 w2 = W(n2, m2, z) + W(-n2, -m2, z); 48 | vec2 w3 = W(n3, m3, z) + W(-n3, -m3, z); 49 | vec2 uv_coord = vec2(ar1 * w1.x - ai1 * w1.y + ar2 * w2.x - ai2 * w2.y + ar3 * w3.x - ai3 * w3.y, 50 | ar1 * w1.y + ai1 * w1.x + ar2 * w2.y + ai2 * w2.x + ar3 * w3.y + ai3 * w3.x); 51 | /* The right sample texture can be rotated by the passed in unif[16][0] 52 | which is pro-ratad across the width. The rotation is done by simple 53 | 2D rotation matrix as below. (vec2(0.5) adjustment to rotate about centre) 54 | */ 55 | float c_angl = mix_f * unif[19][0]; 56 | mat2 rotn = mat2(cos(c_angl), sin(c_angl), 57 | -sin(c_angl), cos(c_angl)); 58 | gl_FragColor = texture2D(tex0, rotn * (uv_coord - vec2(0.5)) + vec2(0.5)); 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/farris_p6_6term.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec2 texcoord; 6 | 7 | uniform mat4 modelviewmatrix[2]; // 0 model movement in real coords, 1 in camera coords 8 | uniform vec3 unib[4]; 9 | //uniform vec2 umult, vmult => unib[2] 10 | //uniform vec2 u_off, v_off => unib[3] 11 | uniform vec3 unif[20]; // hpe 12 | 13 | varying vec2 texcoordout; 14 | 15 | void main(void) { 16 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 17 | gl_Position = modelviewmatrix[1] * vec4(vertex, 1.0); 18 | } 19 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/triangle.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | uniform sampler2D tex0; 5 | uniform sampler2D tex1; 6 | uniform sampler2D tex2; 7 | uniform vec3 unib[4]; 8 | // see docstring Buffer 9 | uniform vec3 unif[20]; 10 | // see docstring Shape 11 | 12 | varying float dist; 13 | varying float fog_start; 14 | varying vec3 normout; 15 | varying vec2 texcoordout; 16 | varying vec3 lightVector; 17 | varying float lightFactor; 18 | 19 | //fragcolor 20 | 21 | void main(void) { 22 | vec4 texc = texture2D(tex0, texcoordout); // ------ material or basic colour from texture 23 | if (texc.a < unib[0][2]) discard; // ------ to allow rendering behind the transparent parts of this object 24 | texc.rgb += unib[1] - vec3(0.5); 25 | float ffact = smoothstep(fog_start, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist 26 | float intensity = clamp(dot(lightVector, vec3(0.0, 0.0, 1.0)) * lightFactor, 0.0, 1.0); // ------ adjustment of colour according to combined normal 27 | texc.rgb = (texc.rgb * unif[9]) * intensity + (texc.rgb * unif[10]); // ------ directional lightcol * intensity + ambient lightcol 28 | gl_FragColor = (1.0 - ffact) * texc + ffact * vec4(unif[4], unif[5][1]); // ------ combine using factors 29 | gl_FragColor.a *= unif[5][2]; 30 | } 31 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/triangle.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec3 normal; 6 | attribute vec2 texcoord; 7 | 8 | uniform mat4 modelviewmatrix[3]; // [0] model movement in real coords, [1] in camera coords, [2] camera at light 9 | uniform vec3 unib[4]; 10 | //uniform float ntiles => unib[0][0] 11 | //uniform vec2 umult, vmult => unib[2] 12 | //uniform vec2 u_off, v_off => unib[3] 13 | uniform vec3 unif[20]; 14 | //uniform vec3 eye > unif[6] 15 | //uniform vec3 lightpos > unif[8] 16 | 17 | varying float dist; 18 | varying float fog_start; 19 | 20 | varying vec2 texcoordout; 21 | varying vec3 lightVector; 22 | varying float lightFactor; 23 | 24 | void main(void) { 25 | vec3 normout; 26 | vec4 relPosn = modelviewmatrix[0] * vec4(vertex, 1.0); 27 | 28 | if (unif[7][0] == 1.0) { // this is a point light and unif[8] is location 29 | lightVector = vec3(relPosn) - unif[8]; 30 | lightFactor = pow(length(lightVector), -2.0); 31 | lightVector = normalize(lightVector); 32 | lightVector.z *= -1.0; 33 | } else { // this is directional light 34 | lightVector = normalize(unif[8]); 35 | lightFactor = 1.0; 36 | } 37 | lightVector.z *= -1.0; 38 | // uvec, vvec are tangent and bitangent vectors at the vertex approx 39 | // lining up with the uv texture mapping. Because (0, 1, 0) is such a 40 | // common normal direction uvec is generated using just off vertical 41 | vec3 uvec = normalize(cross(normal, vec3(0.0003, -1.0, 0.0003))); 42 | vec3 vvec = normalize(cross(uvec, normal)); 43 | normout = normalize(vec3(modelviewmatrix[0] * vec4(normal, 0.0))); 44 | uvec = vec3(modelviewmatrix[0] * vec4(uvec, 0.0)); 45 | vvec = vec3(modelviewmatrix[0] * vec4(vvec, 0.0)); 46 | 47 | lightVector = vec3(mat4(uvec.x, vvec.x, -normout.x, 0.0, 48 | uvec.y, vvec.y, -normout.y, 0.0, 49 | uvec.z, vvec.z, -normout.z, 0.0, 50 | 0.0, 0.0, 0.0, 1.0) * vec4(lightVector, 0.0)); 51 | 52 | vec3 inray = vec3(relPosn - vec4(unif[6], 0.0)); // ----- vector from the camera to this vertex 53 | dist = length(inray); 54 | fog_start = fract(unif[5][0]); 55 | if (fog_start == 0.0) { 56 | fog_start = unif[5][0] * 0.333; 57 | } else { 58 | fog_start *= unif[5][0]; 59 | } 60 | 61 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 62 | 63 | gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); 64 | gl_PointSize = unib[2][2] / dist; 65 | } 66 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_flat_ES30.fs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | uniform sampler2D tex0; 5 | uniform sampler2D tex1; 6 | uniform sampler2D tex2; 7 | uniform vec3 unib[5]; 8 | // see docstring Buffer 9 | uniform vec3 unif[20]; 10 | // see docstring Shape 11 | 12 | in float dist; 13 | in float fog_start; 14 | in vec2 texcoordout; 15 | 16 | out vec4 fragColor; 17 | 18 | void main(void) { 19 | //std_main_uv.inc 20 | // ----- boiler-plate code for fragment shaders with uv textures 21 | 22 | // NB previous define: tex0, texcoordout, unib, unif, dist 23 | 24 | vec4 texc = texture(tex0, texcoordout); // ------ material or basic colour from texture 25 | if (texc.a < unib[0][2]) discard; // ------ to allow rendering behind the transparent parts of this object 26 | texc.rgb += unib[1] - vec3(0.5); 27 | float ffact = smoothstep(fog_start, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist 28 | 29 | fragColor = mix(texc, vec4(unif[4], unif[5][1]), ffact); // ------ combine using factors 30 | fragColor.a *= unif[5][2]; 31 | } 32 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_flat_ES30.vs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | in vec3 vertex; 5 | in vec3 normal; 6 | in vec2 texcoord; 7 | 8 | uniform mat4 modelviewmatrix[3]; // [0] model movement in real coords, [1] in camera coords, [2] camera at light 9 | uniform vec3 unib[5]; 10 | //uniform float ntiles => unib[0][0] 11 | //uniform vec2 umult, vmult => unib[2] 12 | //uniform vec2 u_off, v_off => unib[3] 13 | uniform vec3 unif[20]; 14 | //uniform vec3 eye > unif[6] 15 | //uniform vec3 lightpos > unif[8] 16 | 17 | out float dist; 18 | out float fog_start; 19 | out vec2 texcoordout; 20 | 21 | void main(void) { 22 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 23 | gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); 24 | dist = gl_Position.z; 25 | //std_fog_start.inc 26 | //NB previousl (in std_head_vs.inc) define fog_start and unif[20] 27 | fog_start = fract(unif[5][0]); 28 | if (fog_start == 0.0) { 29 | fog_start = unif[5][0] * 0.333; 30 | } else { 31 | fog_start *= unif[5][0]; 32 | } gl_PointSize = unib[2][2] / dist; 33 | } 34 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_light.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | uniform sampler2D tex0; 5 | uniform sampler2D tex1; 6 | uniform sampler2D tex2; 7 | uniform vec3 unib[4]; 8 | // see docstring Buffer 9 | uniform vec3 unif[20]; 10 | // see docstring Shape 11 | 12 | varying float dist; 13 | varying float fog_start; 14 | varying vec3 normout; 15 | varying vec2 texcoordout; 16 | varying vec3 lightVector; 17 | varying float lightFactor; 18 | 19 | //fragcolor 20 | 21 | void main(void) { 22 | vec4 texc = texture2D(tex0, texcoordout); // ------ material or basic colour from texture 23 | if (texc.a < unib[0][2]) discard; // ------ to allow rendering behind the transparent parts of this object 24 | texc.rgb += unib[1] - vec3(0.5); 25 | float ffact = smoothstep(fog_start, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist 26 | float intensity = clamp(dot(lightVector, vec3(0.0, 0.0, 1.0)) * lightFactor, 0.0, 1.0); // ------ adjustment of colour according to combined normal 27 | texc.rgb = (texc.rgb * unif[9]) * intensity + (texc.rgb * unif[10]); // ------ directional lightcol * intensity + ambient lightcol 28 | 29 | gl_FragColor = (1.0 - ffact) * texc + ffact * vec4(unif[4], unif[5][1]); // ------ combine using factors 30 | gl_FragColor.a *= unif[5][2]; 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_light.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | //precision mediump float; 3 | 4 | attribute vec3 vertex; 5 | attribute vec3 normal; 6 | attribute vec2 texcoord; 7 | 8 | uniform mat4 modelviewmatrix[3]; // [0] model movement in real coords, [1] in camera coords, [2] camera at light 9 | uniform vec3 unib[4]; 10 | //uniform float ntiles => unib[0][0] 11 | //uniform vec2 umult, vmult => unib[2] 12 | //uniform vec2 u_off, v_off => unib[3] 13 | uniform vec3 unif[20]; 14 | //uniform vec3 eye > unif[6] 15 | //uniform vec3 lightpos > unif[8] 16 | 17 | varying float dist; 18 | varying float fog_start; 19 | 20 | varying vec2 texcoordout; 21 | varying vec3 lightVector; 22 | varying float lightFactor; 23 | 24 | void main(void) { 25 | vec3 normout; 26 | vec4 relPosn = modelviewmatrix[0] * vec4(vertex, 1.0); 27 | 28 | if (unif[7][0] == 1.0) { // this is a point light and unif[8] is location 29 | lightVector = vec3(relPosn) - unif[8]; 30 | lightFactor = pow(length(lightVector), -2.0); 31 | lightVector = normalize(lightVector); 32 | lightVector.z *= -1.0; 33 | } else { // this is directional light 34 | lightVector = normalize(unif[8]); 35 | lightFactor = 1.0; 36 | } 37 | lightVector.z *= -1.0; 38 | // uvec, vvec are tangent and bitangent vectors at the vertex approx 39 | // lining up with the uv texture mapping. Because (0, 1, 0) is such a 40 | // common normal direction uvec is generated using just off vertical 41 | vec3 uvec = normalize(cross(normal, vec3(0.0003, -1.0, 0.0003))); 42 | vec3 vvec = normalize(cross(uvec, normal)); 43 | normout = normalize(vec3(modelviewmatrix[0] * vec4(normal, 0.0))); 44 | uvec = vec3(modelviewmatrix[0] * vec4(uvec, 0.0)); 45 | vvec = vec3(modelviewmatrix[0] * vec4(vvec, 0.0)); 46 | 47 | lightVector = vec3(mat4(uvec.x, vvec.x, -normout.x, 0.0, 48 | uvec.y, vvec.y, -normout.y, 0.0, 49 | uvec.z, vvec.z, -normout.z, 0.0, 50 | 0.0, 0.0, 0.0, 1.0) * vec4(lightVector, 0.0)); 51 | 52 | vec3 inray = vec3(relPosn - vec4(unif[6], 0.0)); // ----- vector from the camera to this vertex 53 | dist = length(inray); 54 | fog_start = fract(unif[5][0]); 55 | if (fog_start == 0.0) { 56 | fog_start = unif[5][0] * 0.333; 57 | } else { 58 | fog_start *= unif[5][0]; 59 | } 60 | 61 | texcoordout = texcoord * unib[2].xy + unib[3].xy; 62 | 63 | gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); 64 | gl_PointSize = unib[2][2] / dist; 65 | } 66 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_pointsprite_ES30.fs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | uniform sampler2D tex0; 5 | uniform vec3 unib[5]; 6 | 7 | in float dist; 8 | in mat2 rotn; 9 | in vec2 corner; 10 | in float subsize; 11 | in float alpha; 12 | in vec4 colour; 13 | 14 | out vec4 fragColor; 15 | 16 | const vec2 p_centre = vec2(0.5); 17 | const vec2 limit = vec2(0.6); 18 | 19 | void main(void) { 20 | vec2 rot_coord = rotn * (gl_PointCoord - p_centre); 21 | if (any(greaterThan(abs(rot_coord), limit))) discard; 22 | rot_coord += p_centre; 23 | vec4 texc = texture(tex0, (rot_coord * subsize + corner)); 24 | if (texc.a < unib[0][2]) discard; // ------ to allow rendering behind the transparent parts of this object 25 | fragColor = colour * texc; 26 | //fragColor.a *= texc.a; 27 | } 28 | -------------------------------------------------------------------------------- /pi3d/examples/shaders/uv_pointsprite_ES30.vs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | in vec3 vertex; 5 | in vec3 normal; 6 | in vec2 texcoord; 7 | 8 | uniform mat4 modelviewmatrix[2]; // [0] model movement in real coords, [1] in camera coords 9 | uniform vec3 unib[5]; 10 | //uniform float ntiles => unib[0][0] 11 | //uniform vec2 umult, vmult => unib[2] 12 | //uniform vec2 u_off, v_off => unib[3] 13 | uniform vec3 unif[20]; 14 | 15 | out float dist; 16 | out mat2 rotn; 17 | out vec2 corner; 18 | out float subsize; 19 | out vec4 colour; 20 | 21 | void main(void) { 22 | gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); 23 | dist = vertex[2]; 24 | rotn = mat2(cos(normal[0]), sin(normal[0]), 25 | -sin(normal[0]), cos(normal[0])); 26 | gl_PointSize = unib[2][2] * fract(dist); 27 | corner = texcoord; 28 | subsize = unif[16][0]; 29 | colour = vec4(normal[1]/1000.0, fract(normal[1]), normal[2]/1000.0, fract(normal[2]) ); 30 | } 31 | -------------------------------------------------------------------------------- /pi3d/examples/ship_demo.rs: -------------------------------------------------------------------------------- 1 | extern crate pi3d; 2 | extern crate rand; 3 | extern crate sdl2; 4 | use sdl2::keyboard::Keycode; 5 | 6 | const W: f32 = 1920.0; 7 | const H: f32 = 1080.0; 8 | 9 | fn main() { 10 | let mut display = 11 | pi3d::display::create("ship_demo (C Tim Skillman) window", W, H, "GL", 2, 1).unwrap(); 12 | display.set_background(&[0.1, 0.1, 0.2, 1.0]); 13 | display.set_mouse_relative(true); 14 | display.set_target_fps(1000.0); 15 | let flatsh = pi3d::shader::Program::from_res("uv_flat").unwrap(); 16 | let textsh = pi3d::shader::Program::from_res("uv_pointsprite").unwrap(); 17 | let mut camera = pi3d::camera::create(&display); 18 | let mut camera2d = pi3d::camera::create(&display); 19 | camera2d.set_3d(false); 20 | 21 | let font = pi3d::util::font::create("fonts/NotoSans-Regular.ttf", "", "ęĻ", 64.0); 22 | 23 | let (mut cargo_hold, _texlist) = 24 | pi3d::shapes::model_obj::create(camera.reference(), "models/CargoHoldBaked2.obj"); 25 | cargo_hold.set_shader(&flatsh); 26 | cargo_hold.set_material(&[0.4, 0.4, 0.4]); 27 | cargo_hold.set_fog(&[0.3, 0.3, 0.3], 200.2, 1.0); 28 | let mut radar_num: usize = 0; 29 | for k in 0..cargo_hold.buf.len() { 30 | if cargo_hold.buf[k].array_buffer[[0, 0]] == 97.226921 { 31 | radar_num = k; 32 | break; 33 | } 34 | } 35 | 36 | let (mut ecube, _tex_list) = pi3d::shapes::environment_cube::create( 37 | camera.reference(), 38 | 500.0, 39 | "models/maps/sbox_512", 40 | "png", 41 | ); 42 | ecube.set_shader(&flatsh); 43 | 44 | // fps counter 45 | let mut fps_text = pi3d::shapes::point_text::create(camera2d.reference(), &font, 20, 24.0); 46 | fps_text.set_shader(&textsh); 47 | let fps_blk = fps_text.add_text_block( 48 | &font, 49 | &[-W * 0.5 + 20.0, -H * 0.5 + 20.0, 0.1], 50 | 19, 51 | "00.0 FPS", 52 | ); 53 | 54 | let mut n: usize = 0; 55 | let mut x: f32 = 0.0; 56 | let mut y: f32 = 0.0; 57 | let mut z: f32 = -0.1; 58 | let mut df: f32 = 0.01; 59 | let mut ds: f32 = 0.0; 60 | let mut rot: f32 = 0.0; 61 | let mut tilt: f32 = 0.0; 62 | 63 | while display.loop_running() { 64 | ecube.draw(); 65 | cargo_hold.draw(); 66 | fps_text.set_text(&font, fps_blk, &format!("{:5.1} FPS", display.fps())); 67 | fps_text.draw(); 68 | 69 | n += 1; 70 | if n > 5 { 71 | cargo_hold.buf[radar_num].unib[[3, 0]] += 0.083333; 72 | if cargo_hold.buf[radar_num].unib[[3, 0]] > 1.0 { 73 | cargo_hold.buf[radar_num].unib[[3, 0]] = 0.0; 74 | } 75 | n = 0; 76 | } 77 | 78 | if display.keys_pressed.contains(&Keycode::Escape) { 79 | break; 80 | } 81 | if display.mouse_moved { 82 | tilt = (display.mouse_y as f32 - 300.0) * 0.005; 83 | rot = (display.mouse_x as f32 - 400.0) * 0.005; 84 | } 85 | if display.keys_pressed.contains(&Keycode::W) { 86 | df = 0.5 87 | } 88 | if display.keys_pressed.contains(&Keycode::S) { 89 | df = -0.25; 90 | } 91 | if display.keys_pressed.contains(&Keycode::A) { 92 | ds = 0.25; 93 | } 94 | if display.keys_pressed.contains(&Keycode::D) { 95 | ds = -0.25; 96 | } 97 | let cd = camera.get_direction(); 98 | x += cd[0] * df - cd[2] * ds; 99 | y += cd[1] * df; 100 | z += cd[2] * df + cd[0] * ds; 101 | camera.reset(); 102 | camera.rotate(&[tilt, rot, 0.0]); 103 | if df != 0.0 || ds != 0.0 { 104 | //let (newy, _mapnorm) = pi3d::shapes::elevation_map::calc_height(&map, x, z); 105 | //y = newy + 5.0; 106 | camera.position(&[x, y, z]); 107 | } 108 | ds = 0.0; 109 | df = 0.0; 110 | } 111 | } 112 | 113 | // ========================================================================== 114 | // ship_demo models and image files used by this code made by Tim Skillman 115 | // ========================================================================== 116 | // 117 | // The MIT License 118 | // 119 | // Copyright (c) 2019 Tim Skillman 120 | // 121 | // Permission is hereby granted, free of charge, to any person obtaining a copy 122 | // of this software and associated documentation files (the "Software"), to deal 123 | // in the Software without restriction, including without limitation the rights 124 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 125 | // copies of the Software, and to permit persons to whom the Software is 126 | // furnished to do so, subject to the following conditions: 127 | // 128 | // The above copyright notice and this permission notice shall be included in 129 | // all copies or substantial portions of the Software. 130 | // 131 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 132 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 133 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 134 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 135 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 136 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 137 | // THE SOFTWARE. 138 | // 139 | // Dedicated to the One who has blessed me beyond my dreams ... 140 | // Jesus Christ, King of Kings and Lord of Lords :-) 141 | // ======================================================================= 142 | -------------------------------------------------------------------------------- /pi3d/examples/textures/floor_nm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/floor_nm.jpg -------------------------------------------------------------------------------- /pi3d/examples/textures/grasstile_n.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/grasstile_n.jpg -------------------------------------------------------------------------------- /pi3d/examples/textures/hornbeam2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/hornbeam2.png -------------------------------------------------------------------------------- /pi3d/examples/textures/mountains3_512.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/mountains3_512.jpg -------------------------------------------------------------------------------- /pi3d/examples/textures/mountainsHgt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/mountainsHgt.png -------------------------------------------------------------------------------- /pi3d/examples/textures/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/pattern.png -------------------------------------------------------------------------------- /pi3d/examples/textures/poppy1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/poppy1.jpg -------------------------------------------------------------------------------- /pi3d/examples/textures/stars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/stars.jpg -------------------------------------------------------------------------------- /pi3d/examples/textures/tree1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/tree1.png -------------------------------------------------------------------------------- /pi3d/examples/textures/tree2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/examples/textures/tree2.png -------------------------------------------------------------------------------- /pi3d/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use(s)] 2 | extern crate ndarray; 3 | extern crate gl; 4 | extern crate image; 5 | extern crate rusttype; 6 | #[macro_use] 7 | extern crate lazy_static; 8 | 9 | use std::path::PathBuf; 10 | 11 | lazy_static! { 12 | static ref EXE_PATH: PathBuf = std::env::current_exe().unwrap() 13 | .parent().unwrap() 14 | .into(); 15 | static ref CURRENT_DIR: PathBuf = std::env::current_dir().unwrap(); 16 | static ref GL_ID: String = { 17 | // NB must be run after GL initialized 18 | let mut gl_str = String::from(""); 19 | unsafe { 20 | let version = gl::GetString(gl::VERSION); 21 | for i in 0..12 { 22 | if version.add(i).is_null() || *version.add(1) == 0 { 23 | break; 24 | } 25 | gl_str.push(*version.add(i) as char); 26 | } 27 | } 28 | let mut gl_id = String::from("GL"); 29 | if gl_str.contains("ES") { 30 | gl_id.push_str("ES"); 31 | } 32 | for s in gl_str.split(' ') { 33 | if s.contains('.') { 34 | for n in s.split('.').take(2) { 35 | gl_id.push_str(n); 36 | } 37 | break; 38 | } 39 | } 40 | gl_id 41 | }; 42 | } 43 | 44 | pub mod buffer; 45 | pub mod camera; 46 | pub mod display; 47 | pub mod shader; 48 | pub mod shape; 49 | pub mod texture; 50 | 51 | pub mod shaders; 52 | pub mod shapes; 53 | pub mod util; 54 | -------------------------------------------------------------------------------- /pi3d/src/light.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pi3d/src/light.rs -------------------------------------------------------------------------------- /pi3d/src/shaders/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod built_in_shaders; 2 | -------------------------------------------------------------------------------- /pi3d/src/shapes/cone.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | use crate::{camera, shape, shapes}; 4 | 5 | pub fn create( 6 | cam: Rc>, 7 | radius: f32, 8 | height: f32, 9 | sides: usize, 10 | ) -> shape::Shape { 11 | let path: Vec<[f32; 2]> = vec![ 12 | [0.0, height * 0.5], 13 | [radius * 0.999, -height * 0.499], 14 | [radius, -height * 0.5], 15 | [radius * 0.999, -height * 0.5], 16 | [0.0, -height * 0.5], 17 | ]; 18 | 19 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 20 | } 21 | -------------------------------------------------------------------------------- /pi3d/src/shapes/cuboid.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, shader, buffer}; 5 | 6 | pub fn create( 7 | cam: Rc>, 8 | w: f32, 9 | h: f32, 10 | d: f32, 11 | tw: f32, 12 | th: f32, 13 | td: f32, 14 | ) -> shape::Shape { 15 | let wh = w * 0.5; 16 | let hh = h * 0.5; 17 | let dh = d * 0.5; 18 | let verts: nd::Array2 = nd::arr2(&[ 19 | [-wh, hh, dh], 20 | [wh, hh, dh], 21 | [wh, -hh, dh], 22 | [-wh, -hh, dh], 23 | [wh, hh, dh], 24 | [wh, hh, -dh], 25 | [wh, -hh, -dh], 26 | [wh, -hh, dh], 27 | [-wh, hh, dh], 28 | [-wh, hh, -dh], 29 | [wh, hh, -dh], 30 | [wh, hh, dh], 31 | [wh, -hh, dh], 32 | [wh, -hh, -dh], 33 | [-wh, -hh, -dh], 34 | [-wh, -hh, dh], 35 | [-wh, -hh, dh], 36 | [-wh, -hh, -dh], 37 | [-wh, hh, -dh], 38 | [-wh, hh, dh], 39 | [-wh, hh, -dh], 40 | [-wh, -hh, -dh], 41 | [wh, -hh, -dh], 42 | [wh, hh, -dh], 43 | [0.0, 0.0, 0.0], 44 | ]); 45 | let norms: nd::Array2 = nd::arr2(&[ 46 | [0.0, 0.0, 1.0], 47 | [0.0, 0.0, 1.0], 48 | [0.0, 0.0, 1.0], 49 | [0.0, 0.0, 1.0], 50 | [1.0, 0.0, 0.0], 51 | [1.0, 0.0, 0.0], 52 | [1.0, 0.0, 0.0], 53 | [1.0, 0.0, 0.0], 54 | [0.0, 1.0, 0.0], 55 | [0.0, 1.0, 0.0], 56 | [0.0, 1.0, 0.0], 57 | [0.0, 1.0, 0.0], 58 | [0.0, -1.0, 0.0], 59 | [0.0, -1.0, 0.0], 60 | [0.0, -1.0, 0.0], 61 | [0.0, -1.0, 0.0], 62 | [-1.0, 0.0, 0.0], 63 | [-1.0, 0.0, 0.0], 64 | [-1.0, 0.0, 0.0], 65 | [-1.0, 0.0, 0.0], 66 | [0.0, 0.0, -1.0], 67 | [0.0, 0.0, -1.0], 68 | [0.0, 0.0, -1.0], 69 | [0.0, 0.0, -1.0], 70 | [0.0, 0.0, 0.0], 71 | ]); 72 | let tw = tw * 0.5; 73 | let th = th * 0.5; 74 | let td = td * 0.5; 75 | let texcoords: nd::Array2 = nd::arr2(&[ 76 | [0.5 + tw, 0.5 - th], 77 | [0.5 - tw, 0.5 - th], 78 | [0.5 - tw, 0.5 + th], 79 | [0.5 + tw, 0.5 + th], // tw x th 80 | [0.5 + td, 0.5 - th], 81 | [0.5 - td, 0.5 - th], 82 | [0.5 - td, 0.5 + th], 83 | [0.5 + td, 0.5 + th], // td x th 84 | [0.5 + tw, 0.5 + td], 85 | [0.5 + tw, 0.5 - td], 86 | [0.5 - tw, 0.5 - td], 87 | [0.5 - tw, 0.5 + td], // tw x td 88 | [0.5 + tw, 0.5 + td], 89 | [0.5 + tw, 0.5 - td], 90 | [0.5 - tw, 0.5 - td], 91 | [0.5 - tw, 0.5 + td], // tw x td 92 | [0.5 - td, 0.5 + th], 93 | [0.5 + td, 0.5 + th], 94 | [0.5 + td, 0.5 - th], 95 | [0.5 - td, 0.5 - th], // td x th 96 | [0.5 - tw, 0.5 - th], 97 | [0.5 - tw, 0.5 + th], 98 | [0.5 + tw, 0.5 + th], 99 | [0.5 + tw, 0.5 - th], 100 | [0.0, 0.0], // tw x th 101 | ]); 102 | let faces: nd::Array2 = nd::arr2(&[ 103 | [1, 0, 3], 104 | [3, 2, 1], 105 | [5, 4, 7], 106 | [7, 6, 5], 107 | [9, 8, 11], 108 | [11, 10, 9], 109 | [14, 13, 12], 110 | [12, 15, 14], 111 | [17, 16, 19], 112 | [19, 18, 17], 113 | [21, 20, 23], 114 | [23, 22, 21], 115 | ]); 116 | let new_buffer = buffer::create( 117 | &shader::Program::new(), 118 | verts, 119 | norms, 120 | texcoords, 121 | faces, 122 | true, 123 | ); 124 | shape::create(vec![new_buffer], cam) 125 | } 126 | -------------------------------------------------------------------------------- /pi3d/src/shapes/cylinder.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | use crate::{camera, shape, shapes}; 4 | 5 | pub fn create( 6 | cam: Rc>, 7 | radius: f32, 8 | height: f32, 9 | sides: usize, 10 | ) -> shape::Shape { 11 | let path: Vec<[f32; 2]> = vec![ 12 | [0.0, height * 0.5], 13 | [radius * 0.999, height * 0.5], 14 | [radius, height * 0.5], 15 | [radius, height * 0.499], 16 | [radius, -height * 0.499], 17 | [radius, -height * 0.5], 18 | [radius * 0.999, -height * 0.5], 19 | [0.0, -height * 0.5], 20 | ]; 21 | 22 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 23 | } 24 | -------------------------------------------------------------------------------- /pi3d/src/shapes/elevation_map.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::util::{resources, vec3}; 5 | use crate::{camera, shape, shader, buffer}; 6 | 7 | // create a new struct definition 8 | pub struct ElevationMap { 9 | pub shape: shape::Shape, 10 | ix: f32, 11 | iz: f32, 12 | width: f32, 13 | depth: f32, 14 | } 15 | 16 | /// generate an elevation map Shape 17 | /// 18 | /// * `disp` reference to the display object which has file path functionality 19 | /// * `mapfile` relative path to image file representing heights 20 | /// * `width` edge to edge in x direction 21 | /// * `depth` in z direction 22 | /// * `height` in y direction scaled by pixel values 0 to 255 23 | /// * `ix` number of polygons in x direction 24 | /// * `iz` polygons in z direction 25 | /// * `ntiles` uv repeats for texture mapping 26 | /// * `_texmap` TODO used for allocating multiple textures to the map 27 | /// NB for no image scaling the mapfile should be one more pixel than ix and iz 28 | /// i.e. 33x33 image for 32x32 squares in grid 29 | /// 30 | /// TODO put this as class method (i.e. ::new()) 31 | pub fn new( 32 | cam: Rc>, 33 | mapfile: &str, 34 | width: f32, 35 | depth: f32, 36 | height: f32, 37 | ix: usize, 38 | iz: usize, 39 | ntiles: f32, 40 | _texmap: &str, 41 | ) -> ElevationMap { 42 | let ix = if ix < 200 { ix + 1 } else { 200 }; // one more vertex in each direction than number of divisions 43 | let iz = if iz < 200 { iz + 1 } else { 200 }; 44 | //let res = ::util::resources::from_exe_path().unwrap(); 45 | let f = resources::resource_name_to_path(mapfile); 46 | //println!("f={:?}", f); 47 | let im = image::open(f).unwrap(); 48 | // convert to Gray 49 | let mut im = image::imageops::colorops::grayscale(&im); 50 | // resize 51 | let (w, h) = im.dimensions(); 52 | if w != ix as u32 || h != iz as u32 { 53 | im = image::imageops::resize(&im, ix as u32, iz as u32, image::FilterType::Lanczos3); 54 | } 55 | // flip top to bottom and left to right - which results in 180 degree rotation 56 | let im = image::imageops::rotate180(&im); 57 | let pixels = nd::Array::from_shape_vec((iz, ix, 1), im.into_raw()).unwrap(); 58 | 59 | //TODO texmap used for mapping other info into uv coords (integer part) 60 | 61 | let wh = width * 0.5; 62 | let hh = depth * 0.5; 63 | let ws = width / (ix as f32 - 1.0); 64 | let hs = depth / (iz as f32 - 1.0); 65 | let ht = height / 255.0; 66 | let tx = 1.0 * ntiles / ix as f32; 67 | let tz = 1.0 * ntiles / iz as f32; 68 | 69 | let mut verts = Vec::::new(); 70 | let mut faces = Vec::::new(); 71 | let mut tex_coords = Vec::::new(); 72 | 73 | for z in 0..iz { 74 | for x in 0..ix { 75 | //println!("z,x {:?},{:?}", z, x); 76 | verts.extend_from_slice(&[ 77 | -wh + x as f32 * ws, 78 | pixels[[z, x, 0]] as f32 * ht, 79 | -hh + z as f32 * hs, 80 | ]); 81 | tex_coords.extend_from_slice(&[(ix - x) as f32 * tx, (iz - z) as f32 * tz]); 82 | } 83 | } 84 | 85 | //create one long triangle_strip by alternating X directions 86 | for z in 0..(iz - 1) { 87 | for x in 0..(ix - 1) { 88 | let i = (z * ix) + x; 89 | faces.extend_from_slice(&[i as u16, (i + ix) as u16, (i + ix + 1) as u16]); 90 | faces.extend_from_slice(&[(i + ix + 1) as u16, (i + 1) as u16, i as u16]); 91 | } 92 | } 93 | 94 | let nverts = verts.len() / 3; 95 | let nfaces = faces.len() / 3; 96 | let new_buffer = buffer::create( 97 | &shader::Program::new(), 98 | nd::Array::from_shape_vec((nverts, 3usize), verts).unwrap(), 99 | nd::Array2::::zeros((0, 3)), 100 | nd::Array::from_shape_vec((nverts, 2usize), tex_coords).unwrap(), 101 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 102 | true, 103 | ); 104 | let shape = shape::create(vec![new_buffer], cam); 105 | ElevationMap { 106 | shape, 107 | ix: ix as f32 - 1.0, // hold these for calc_height in additional attributes 108 | iz: iz as f32 - 1.0, 109 | width, 110 | depth, 111 | } 112 | } 113 | 114 | /// find the value of the y component of the location on the triangle 115 | /// where the x, z location lies within the elevation_map 116 | /// 117 | /// * `px` x location in world space 118 | /// * `pz` z location 119 | /// 120 | /// returns a tuple of the (height, normal vector at that point) this can 121 | /// be used for resistance to movement, bouncing etc. 122 | impl ElevationMap { 123 | pub fn calc_height(&self, px: f32, pz: f32) -> (f32, Vec) { 124 | //TODO a) the skip method will only work for regular maps 125 | // b) Buffer.calc_normals does cross product calc already so should save result 126 | // in Buffer on creation 127 | let px = px - self.shape.unif[[0, 0]]; 128 | let pz = pz - self.shape.unif[[0, 2]]; 129 | let skip_n = (((pz + self.depth * 0.5) * self.iz / self.depth).floor() * self.ix * 2.0 130 | + ((px + self.width * 0.5) * self.ix / self.width).floor() * 2.0) 131 | as usize; 132 | for f in self.shape.buf[0] 133 | .element_array_buffer 134 | .axis_iter(nd::Axis(0)) 135 | .skip(skip_n) 136 | { 137 | let mut v: Vec> = vec![vec![0.0; 3]; 3]; 138 | for i in 0..3 { 139 | // the three vertices of this element 140 | for j in 0..3 { 141 | // the x, y, z components of each vertex 142 | v[i][j] = self.shape.buf[0].array_buffer[[f[[i]] as usize, j]]; 143 | } 144 | } 145 | if ((v[1][2] - v[0][2]) * (px - v[0][0]) + (-v[1][0] + v[0][0]) * (pz - v[0][2]) >= 0.0) 146 | && ((v[2][2] - v[1][2]) * (px - v[1][0]) + (-v[2][0] + v[1][0]) * (pz - v[1][2]) 147 | >= 0.0) 148 | && ((v[0][2] - v[2][2]) * (px - v[2][0]) + (-v[0][0] + v[2][0]) * (pz - v[2][2]) 149 | >= 0.0) 150 | { 151 | let v0 = nd::arr1(&v[0]); 152 | let v1 = nd::arr1(&v[1]); 153 | let v2 = nd::arr1(&v[2]); 154 | //calc normal from two edge vectors v2-v1 and v3-v1 155 | let n_vec = vec3::cross(&(&v1 - &v0), &(v2 - v0)); 156 | //equation of plane: Ax + By + Cz = k_val where A,B,C are components of normal. x,y,z for point v1 to find k_val 157 | let k_val = vec3::dot(&n_vec, &v1); 158 | //return y val i.e. y = (k_val - Ax - Cz)/B also the normal vector seeing as this has been calculated 159 | return ( 160 | (k_val - n_vec[[0]] * px - n_vec[[2]] * pz) / n_vec[[1]], 161 | n_vec.to_vec(), 162 | ); 163 | } 164 | } 165 | //TODO fn should return Option<> and need to be unwrapped rather than return something 166 | (0.0, vec![0.0, 1.0, 0.0]) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /pi3d/src/shapes/environment_cube.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::collections::HashMap; 4 | use std::rc::Rc; 5 | use crate::{camera, shape, buffer, texture, shader}; 6 | 7 | /// generate an enviroment cube which uses six textures 8 | /// 9 | /// * `disp` reference to the display object which has file path functionality 10 | /// * `size` cube width 11 | /// * `stem` stem of the name, i.e. before '_back' '_front' etc 12 | /// * `suffix` i.e. jpg, png etc 13 | /// 14 | /// NB this function returns a tuple of Shape and Vec of Texture object 15 | /// as they will need to live as long as the enviroment cube is used 16 | /// 17 | pub fn create( 18 | cam: Rc>, 19 | size: f32, 20 | stem: &str, 21 | suffix: &str, 22 | ) -> (shape::Shape, HashMap) { 23 | let parts = vec!["front", "right", "top", "bottom", "left", "back"]; 24 | let mut bufs = Vec::::new(); 25 | let ww = size / 2.0; 26 | let hh = size / 2.0; 27 | let dd = size / 2.0; 28 | //TODO why does the uv array need a 'sacrificial' entry on the end? 29 | bufs.push(buffer::create( 30 | &shader::Program::new(), 31 | nd::arr2(&[ 32 | [-ww, hh, dd], 33 | [ww, hh, dd], 34 | [ww, -hh, dd], 35 | [-ww, -hh, dd], 36 | [0.0, 0.0, 0.0], 37 | ]), 38 | nd::arr2(&[ 39 | [0.0, 0.0, 1.0], 40 | [0.0, 0.0, 1.0], 41 | [0.0, 0.0, 1.0], 42 | [0.0, 0.0, 1.0], 43 | [0.0, 0.0, 0.0], 44 | ]), 45 | nd::arr2(&[ 46 | [0.002, 0.002], 47 | [0.998, 0.002], 48 | [0.998, 0.998], 49 | [0.002, 0.998], 50 | [0.0, 0.0], 51 | ]), 52 | nd::arr2(&[[3, 0, 1], [2, 3, 1]]), 53 | false, 54 | )); //front 55 | 56 | bufs.push(buffer::create( 57 | &shader::Program::new(), 58 | nd::arr2(&[ 59 | [ww, hh, dd], 60 | [ww, hh, -dd], 61 | [ww, -hh, -dd], 62 | [ww, -hh, dd], 63 | [0.0, 0.0, 0.0], 64 | ]), 65 | nd::arr2(&[ 66 | [1.0, 0.0, 0.0], 67 | [1.0, 0.0, 0.0], 68 | [1.0, 0.0, 0.0], 69 | [1.0, 0.0, 0.0], 70 | [0.0, 0.0, 0.0], 71 | ]), 72 | nd::arr2(&[ 73 | [0.002, 0.002], 74 | [0.998, 0.002], 75 | [0.998, 0.998], 76 | [0.002, 0.998], 77 | [0.0, 0.0], 78 | ]), 79 | nd::arr2(&[[3, 0, 1], [2, 3, 1]]), 80 | false, 81 | )); //right 82 | 83 | bufs.push(buffer::create( 84 | &shader::Program::new(), 85 | nd::arr2(&[ 86 | [-ww, hh, dd], 87 | [-ww, hh, -dd], 88 | [ww, hh, -dd], 89 | [ww, hh, dd], 90 | [0.0, 0.0, 0.0], 91 | ]), 92 | nd::arr2(&[ 93 | [0.0, 1.0, 0.0], 94 | [0.0, 1.0, 0.0], 95 | [0.0, 1.0, 0.0], 96 | [0.0, 1.0, 0.0], 97 | [0.0, 0.0, 0.0], 98 | ]), 99 | nd::arr2(&[ 100 | [0.002, 0.998], 101 | [0.002, 0.002], 102 | [0.998, 0.002], 103 | [0.998, 0.998], 104 | [0.0, 0.0], 105 | ]), 106 | nd::arr2(&[[3, 0, 1], [2, 3, 1]]), 107 | false, 108 | )); //top 109 | 110 | bufs.push(buffer::create( 111 | &shader::Program::new(), 112 | nd::arr2(&[ 113 | [ww, -hh, dd], 114 | [ww, -hh, -dd], 115 | [-ww, -hh, -dd], 116 | [-ww, -hh, dd], 117 | [0.0, 0.0, 0.0], 118 | ]), 119 | nd::arr2(&[ 120 | [0.0, -1.0, 0.0], 121 | [0.0, -1.0, 0.0], 122 | [0.0, -1.0, 0.0], 123 | [0.0, -1.0, 0.0], 124 | [0.0, 0.0, 0.0], 125 | ]), 126 | nd::arr2(&[ 127 | [0.998, 0.002], 128 | [0.998, 0.998], 129 | [0.002, 0.998], 130 | [0.002, 0.002], 131 | [0.0, 0.0], 132 | ]), 133 | nd::arr2(&[[3, 0, 1], [2, 3, 1]]), 134 | false, 135 | )); //bottom 136 | 137 | bufs.push(buffer::create( 138 | &shader::Program::new(), 139 | nd::arr2(&[ 140 | [-ww, -hh, dd], 141 | [-ww, -hh, -dd], 142 | [-ww, hh, -dd], 143 | [-ww, hh, dd], 144 | [0.0, 0.0, 0.0], 145 | ]), 146 | nd::arr2(&[ 147 | [-1.0, 0.0, 0.0], 148 | [-1.0, 0.0, 0.0], 149 | [-1.0, 0.0, 0.0], 150 | [-1.0, 0.0, 0.0], 151 | [0.0, 0.0, 0.0], 152 | ]), 153 | nd::arr2(&[ 154 | [0.998, 0.998], 155 | [0.002, 0.998], 156 | [0.002, 0.002], 157 | [0.998, 0.002], 158 | [0.0, 0.0], 159 | ]), 160 | nd::arr2(&[[3, 0, 1], [2, 3, 1]]), 161 | false, 162 | )); //left 163 | 164 | bufs.push(buffer::create( 165 | &shader::Program::new(), 166 | nd::arr2(&[ 167 | [-ww, hh, -dd], 168 | [ww, hh, -dd], 169 | [ww, -hh, -dd], 170 | [-ww, -hh, -dd], 171 | [0.0, 0.0, 0.0], 172 | ]), 173 | nd::arr2(&[ 174 | [0.0, 0.0, -1.0], 175 | [0.0, 0.0, -1.0], 176 | [0.0, 0.0, -1.0], 177 | [0.0, 0.0, -1.0], 178 | [0.0, 0.0, 0.0], 179 | ]), 180 | nd::arr2(&[ 181 | [0.998, 0.002], 182 | [0.002, 0.002], 183 | [0.002, 0.998], 184 | [0.998, 0.998], 185 | [0.0, 0.0], 186 | ]), 187 | nd::arr2(&[[3, 1, 0], [2, 1, 3]]), 188 | false, 189 | )); //back 190 | 191 | let mut tex_list = HashMap::::new(); 192 | 193 | for i in 0..bufs.len() { 194 | //let path_str = path_buf.to_str().unwrap(); 195 | let fname = format!("{}_{}.{}", &stem, &parts[i], &suffix); 196 | let tex = texture::create_from_file(&fname); 197 | bufs[i].set_textures(&vec![tex.id]); 198 | tex_list.insert(parts[i].to_string(), tex); 199 | } 200 | let mut new_shape = shape::create(bufs, cam); 201 | new_shape.set_fog(&[0.5, 0.5, 0.5], 5000.0, 1.0); 202 | (new_shape, tex_list) 203 | } 204 | -------------------------------------------------------------------------------- /pi3d/src/shapes/lathe.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::f32::consts; 4 | use std::rc::Rc; 5 | use crate::{camera, shape, buffer, shader}; 6 | 7 | pub fn create( 8 | cam: Rc>, 9 | path: Vec<[f32; 2]>, 10 | sides: usize, 11 | rise: f32, 12 | loops: f32, 13 | ) -> shape::Shape { 14 | let s = path.len(); // iterations along path 15 | let rl = sides * loops as usize; // iterations around axis 16 | 17 | let mut pn: u16 = 0; // keep track of vert index for faces 18 | let mut pp: u16 = 0; // ditto 19 | let tcx = 1.0 / sides as f32; // UV step horizontally 20 | let pr = (consts::PI / sides as f32) * 2.0; // angle rotated per vertex 21 | let rdiv = rise / rl as f32; // increment axially each step 22 | 23 | // Find length of the path 24 | let mut path_len = 0.0; 25 | for p in 1..s { 26 | path_len += ((path[p][0] - path[p - 1][0]).powf(2.0) 27 | + (path[p][1] - path[p - 1][1]).powf(2.0)) 28 | .powf(0.5); 29 | } 30 | 31 | let mut verts = Vec::::new(); 32 | let mut norms = Vec::::new(); 33 | let mut faces = Vec::::new(); 34 | let mut tex_coords = Vec::::new(); 35 | 36 | let mut opx = path[0][0]; 37 | let mut opy = path[0][1]; 38 | 39 | let mut tcy = 0.0; // UV val vertically 40 | for p in 0..s { 41 | let px = path[p][0]; // for brevity 42 | let mut py = path[p][1]; // and clarity (and need to increment!) 43 | let step_len = ((px - opx).powf(2.0) + (py - opy).powf(2.0)).powf(0.5); 44 | if p > 0 { 45 | tcy += step_len / path_len; 46 | } 47 | let dx = (px - opx) / step_len; 48 | let dy = (py - opy) / step_len; 49 | 50 | for r in 0..(rl + 1) { 51 | let sinr = (pr * r as f32).sin(); 52 | let cosr = (pr * r as f32).cos(); 53 | verts.extend_from_slice(&[px * sinr, py, px * cosr]); 54 | norms.extend_from_slice(&[-sinr * dy, dx, -cosr * dy]); 55 | tex_coords.extend_from_slice(&[1.0 - tcx * r as f32, tcy]); 56 | py += rdiv; 57 | } 58 | if p < (s - 1) { 59 | pn += rl as u16 + 1; 60 | for r in 0..rl { 61 | faces.extend_from_slice(&[pp + r as u16 + 1, pp + r as u16, pn + r as u16]); 62 | faces.extend_from_slice(&[pn + r as u16, pn + r as u16 + 1, pp + r as u16 + 1]); 63 | } 64 | pp += rl as u16 + 1; 65 | } 66 | opx = px; 67 | opy = py; 68 | } 69 | let nverts = verts.len() / 3; 70 | let nfaces = faces.len() / 3; 71 | let new_buffer = buffer::create( 72 | &shader::Program::new(), 73 | nd::Array::from_shape_vec((nverts, 3usize), verts).unwrap(), //TODO make functions return Result and feedback errors 74 | nd::Array::from_shape_vec((nverts, 3usize), norms).unwrap(), 75 | nd::Array::from_shape_vec((nverts, 2usize), tex_coords).unwrap(), 76 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 77 | false, 78 | ); 79 | shape::create(vec![new_buffer], cam) 80 | } 81 | -------------------------------------------------------------------------------- /pi3d/src/shapes/lines.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, buffer, shader}; 5 | 6 | pub fn create( 7 | cam: Rc>, 8 | verts: &[f32], 9 | line_width: f32, 10 | closed: bool, 11 | ) -> shape::Shape { 12 | //TODO sort out reason for extra vertex (uv point) 13 | let norms = nd::Array2::::zeros((0, 3)); 14 | let tex_coords = nd::Array2::::zeros((0, 2)); 15 | let nverts = verts.len() / 3; 16 | let nfaces = nverts / 3 + 1; 17 | let mut faces = Vec::::new(); 18 | for a in 0..nfaces { 19 | for i in 0..3 { 20 | let v = a * 3 + i; 21 | faces.push(if v < nverts { v } else { nverts - 1 } as u16); 22 | } 23 | } 24 | 25 | let mut new_buffer = buffer::create( 26 | &shader::Program::new(), 27 | nd::Array::from_shape_vec((nverts, 3usize), verts.to_vec()).unwrap(), //TODO make functions return Result and feedback errors 28 | norms, 29 | tex_coords, 30 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 31 | false, 32 | ); 33 | 34 | new_buffer.set_line_width(line_width, true, closed); 35 | 36 | shape::create(vec![new_buffer], cam) 37 | } 38 | -------------------------------------------------------------------------------- /pi3d/src/shapes/merge_shape.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::f32::consts; 4 | use std::rc::Rc; 5 | 6 | use crate::util::vec3::{rotate_vec, rotate_vec_slice}; 7 | use crate::{shape, shapes, buffer, shader, camera}; 8 | 9 | /// add a Vec of Buffers at specific location, rotation, scales to an existing 10 | /// Shape 11 | /// 12 | /// * `merge_to` existing shape to merge new shapes to 13 | /// * `new_bufs` Vec of &Buffer objects to build into merge_to 14 | /// * `loc` Vec of [x, y, z] locations matching each Buffer in new_bufs 15 | /// * `rot` Vec of [rx, ry, rz] rotations 16 | /// * `scl` Vec of [sx, sy, sz] scales 17 | /// * `num` Vec of index values to merge_to.buf[] for merging new Buffers 18 | /// 19 | pub fn add_buffers( 20 | merge_to: &mut shape::Shape, 21 | new_bufs: Vec<&buffer::Buffer>, 22 | loc: Vec<[f32; 3]>, 23 | rot: Vec<[f32; 3]>, 24 | scl: Vec<[f32; 3]>, 25 | num: Vec, 26 | ) { 27 | if new_bufs.len() != loc.len() || loc.len() != rot.len() || rot.len() != scl.len() { 28 | panic!("\n\nadd_buffers() needs four Vecs of same size\n\n"); 29 | } 30 | // make note of num of verts and faces already there. 31 | // also have a new mut num_v, verts, norms, tex_coord and faces for each num 32 | let mut num_v = Vec::::new(); 33 | let mut verts = Vec::>::new(); 34 | let mut norms = Vec::>::new(); 35 | let mut tex_coords = Vec::>::new(); 36 | let mut faces = Vec::>::new(); 37 | let mut new_buf_ix = Vec::::new(); 38 | for i in 0..merge_to.buf.len() { 39 | num_v.push(merge_to.buf[i].array_buffer.shape()[0] as u16); 40 | verts.push(merge_to.buf[i].array_buffer.slice(s![.., 0..3]).to_owned()); 41 | norms.push(merge_to.buf[i].array_buffer.slice(s![.., 3..6]).to_owned()); 42 | tex_coords.push(merge_to.buf[i].array_buffer.slice(s![.., 6..8]).to_owned()); 43 | faces.push(merge_to.buf[i].element_array_buffer.to_owned()); 44 | new_buf_ix.push(0); 45 | } 46 | for i in 0..new_bufs.len() { 47 | // if num >= merge_to.buf.len() -> add new empty buffers to bring to size 48 | while num[i] >= merge_to.buf.len() { 49 | merge_to.buf.push(buffer::create_empty()); 50 | num_v.push(0); // and crete empty buffers 51 | verts.push( 52 | merge_to.buf[0] 53 | .array_buffer 54 | .slice(s![0..0, 0..3]) 55 | .to_owned(), 56 | ); 57 | norms.push( 58 | merge_to.buf[0] 59 | .array_buffer 60 | .slice(s![0..0, 3..6]) 61 | .to_owned(), 62 | ); 63 | tex_coords.push( 64 | merge_to.buf[0] 65 | .array_buffer 66 | .slice(s![0..0, 6..8]) 67 | .to_owned(), 68 | ); 69 | faces.push( 70 | merge_to.buf[0] 71 | .element_array_buffer 72 | .slice(s![0..0, ..]) 73 | .to_owned(), 74 | ); 75 | new_buf_ix.push(0); 76 | } 77 | // scale then rotate new verts then add displacement 78 | let new_verts = &new_bufs[i].array_buffer.slice(s![.., 0..3]) * &nd::arr1(&scl[i]); 79 | let new_verts = rotate_vec(&rot[i], &new_verts) + &nd::arr1(&loc[i]); 80 | // then add them to existing verts 81 | verts[num[i]].append(nd::Axis(0), new_verts.view()).unwrap(); 82 | // rotate new normals 83 | let new_norms = rotate_vec_slice(&rot[i], &new_bufs[i].array_buffer.slice(s![.., 3..6])); 84 | // then add them to existing normals 85 | norms[num[i]].append(nd::Axis(0), new_norms.view()).unwrap(); 86 | // stack tex_coords 87 | tex_coords[num[i]].append(nd::Axis(0), new_bufs[i].array_buffer.slice(s![.., 6..8]).view()).unwrap(); 88 | // add num_v to values in faces 89 | faces[num[i]].append(nd::Axis(0), (&new_bufs[i].element_array_buffer + num_v[num[i]]).view()).unwrap(); 90 | num_v[num[i]] += new_verts.shape()[0] as u16; 91 | new_buf_ix[num[i]] = i; 92 | } 93 | for i in 0..merge_to.buf.len() { 94 | let mut extended_buf = buffer::create( 95 | &shader::Program::new(), 96 | verts[i].to_owned(), 97 | norms[i].to_owned(), 98 | tex_coords[i].to_owned(), 99 | faces[i].to_owned(), 100 | false, 101 | ); 102 | // copy over shader, textures, unib, draw_method 103 | let ix = new_buf_ix[i]; 104 | extended_buf.unib = new_bufs[ix].unib.clone(); 105 | extended_buf.draw_method = new_bufs[ix].draw_method; 106 | extended_buf.shader_id = new_bufs[ix].shader_id; 107 | extended_buf.attribute_names = new_bufs[ix].attribute_names.clone(); 108 | extended_buf.attribute_values = new_bufs[ix].attribute_values.clone(); 109 | extended_buf.uniform_names = new_bufs[ix].uniform_names.clone(); 110 | extended_buf.uniform_values = new_bufs[ix].uniform_values.clone(); 111 | extended_buf.textures = new_bufs[ix].textures.clone(); 112 | merge_to.buf[i] = extended_buf; 113 | } 114 | } 115 | 116 | /// wrapper round add_buffers that can be passed a Vec of Shape objects 117 | /// and will the buf Vec and add all the Buffer objects 118 | /// 119 | pub fn add_shapes( 120 | merge_to: &mut shape::Shape, 121 | new_shapes: Vec<&shape::Shape>, 122 | loc: Vec<[f32; 3]>, 123 | rot: Vec<[f32; 3]>, 124 | scl: Vec<[f32; 3]>, 125 | num: Vec, 126 | ) { 127 | let mut bufs = Vec::<&buffer::Buffer>::new(); 128 | let mut new_loc = Vec::<[f32; 3]>::new(); 129 | let mut new_rot = Vec::<[f32; 3]>::new(); 130 | let mut new_scl = Vec::<[f32; 3]>::new(); 131 | let mut new_num = Vec::::new(); 132 | for i in 0..new_shapes.len() { 133 | for j in 0..new_shapes[i].buf.len() { 134 | bufs.push(&new_shapes[i].buf[j]); 135 | new_loc.push([loc[i][0], loc[i][1], loc[i][2]]); 136 | new_rot.push([rot[i][0], rot[i][1], rot[i][2]]); 137 | new_scl.push([scl[i][0], scl[i][1], scl[i][2]]); 138 | new_num.push(num[i]); 139 | } 140 | } 141 | add_buffers(merge_to, bufs, new_loc, new_rot, new_scl, new_num); 142 | } 143 | 144 | /// create a cluster of shapes on an elevation map 145 | /// 146 | /// * `merge_to` existing Shape to merge cluster of duplicate shapes to 147 | /// * `new_shape' new Shape to duplicate 148 | /// * `map' elevation_map for calculating height 149 | /// * `xpos`, `ypos` centre of cluster 150 | /// * `w`, `d` width and depth of cluster 151 | /// * `minscl`, `maxscl` range of scaling factors to apply 152 | /// * `count` number of duplicates to make 153 | /// 154 | pub fn cluster( 155 | merge_to: &mut shape::Shape, 156 | new_shape: &shape::Shape, 157 | map: &shapes::elevation_map::ElevationMap, 158 | xpos: f32, 159 | zpos: f32, 160 | w: f32, 161 | d: f32, 162 | minscl: f32, 163 | maxscl: f32, 164 | count: usize, 165 | ) { 166 | let mut bufs = Vec::<&buffer::Buffer>::new(); 167 | let mut new_loc = Vec::<[f32; 3]>::new(); 168 | let mut new_rot = Vec::<[f32; 3]>::new(); 169 | let mut new_scl = Vec::<[f32; 3]>::new(); 170 | let mut new_num = Vec::::new(); 171 | for _i in 0..count { 172 | let x = xpos - 0.5 * w + w * rand::random::(); 173 | let z = zpos - 0.5 * d + d * rand::random::(); 174 | let (y, _norm) = map.calc_height(x, z); 175 | let ry = 2.0 * consts::PI * rand::random::(); 176 | let scl = minscl + (maxscl - minscl) * rand::random::(); 177 | for j in 0..new_shape.buf.len() { 178 | bufs.push(&new_shape.buf[j]); 179 | new_loc.push([x, y, z]); 180 | new_rot.push([0.0, ry, 0.0]); 181 | new_scl.push([scl, scl, scl]); 182 | new_num.push(j); 183 | } 184 | } 185 | 186 | add_buffers(merge_to, bufs, new_loc, new_rot, new_scl, new_num); 187 | } 188 | 189 | /// initial creation produces a shape with an empty buffer 190 | /// 191 | pub fn create(cam: Rc>) -> shape::Shape { 192 | let new_buffer = buffer::create_empty(); 193 | shape::create(vec![new_buffer], cam) 194 | } 195 | 196 | //TODO pub fn radial_copy(); 197 | -------------------------------------------------------------------------------- /pi3d/src/shapes/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate image; 2 | 3 | pub mod cone; 4 | pub mod cuboid; 5 | pub mod cylinder; 6 | pub mod elevation_map; 7 | pub mod environment_cube; 8 | pub mod lathe; 9 | pub mod lines; 10 | pub mod merge_shape; 11 | pub mod model_obj; 12 | pub mod plane; 13 | pub mod point_text; 14 | pub mod points; 15 | pub mod sphere; 16 | pub mod string; 17 | pub mod tcone; 18 | pub mod torus; 19 | pub mod tube; 20 | -------------------------------------------------------------------------------- /pi3d/src/shapes/plane.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, buffer, shader}; 5 | 6 | pub fn create(cam: Rc>, w: f32, h: f32) -> shape::Shape { 7 | let wh = w * 0.5; 8 | let hh = h * 0.5; 9 | //TODO sort out reason for extra vertex (uv point) 10 | let verts: nd::Array2 = nd::arr2(&[ 11 | [-wh, hh, 0.0], 12 | [wh, hh, 0.0], 13 | [wh, -hh, 0.0], 14 | [-wh, -hh, 0.0], 15 | [-wh, hh, 0.0], 16 | [wh, hh, 0.0], 17 | [wh, -hh, 0.0], 18 | [-wh, -hh, 0.0], 19 | [0.0, 0.0, 0.0], 20 | ]); 21 | let norms: nd::Array2 = nd::arr2(&[ 22 | [-wh, hh, 0.0], 23 | [wh, hh, 0.0], 24 | [wh, -hh, 0.0], 25 | [-wh, -hh, 0.0], 26 | [-wh, hh, 0.0], 27 | [wh, hh, 0.0], 28 | [wh, -hh, 0.0], 29 | [-wh, -hh, 0.0], 30 | [0.0, 0.0, 0.0], 31 | ]); 32 | let texcoords: nd::Array2 = nd::arr2(&[ 33 | [0.0, 0.0], 34 | [1.0, 0.0], 35 | [1.0, 1.0], 36 | [0.0, 1.0], 37 | [0.0, 0.0], 38 | [1.0, 0.0], 39 | [1.0, 1.0], 40 | [0.0, 1.0], 41 | [0.0, 0.0], 42 | ]); 43 | let faces: nd::Array2 = nd::arr2(&[[3, 0, 1], [1, 2, 3], [7, 6, 5], [5, 4, 7]]); 44 | 45 | let new_buffer = buffer::create( 46 | &shader::Program::new(), 47 | verts, 48 | norms, 49 | texcoords, 50 | faces, 51 | true, 52 | ); 53 | shape::create(vec![new_buffer], cam) 54 | } 55 | -------------------------------------------------------------------------------- /pi3d/src/shapes/point_text.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | use crate::{camera, shape, shapes, shader}; 4 | use crate::util::font; 5 | 6 | pub struct TextBlock { 7 | x: f32, 8 | y: f32, 9 | z: f32, 10 | capacity: usize, 11 | size: f32, 12 | text: String, 13 | rot: f32, 14 | char_rot: f32, 15 | spacing: char, 16 | space: f32, 17 | rgba: [f32; 4], 18 | justification: f32, 19 | start: usize, 20 | } 21 | 22 | pub struct PointText { 23 | pub points: shape::Shape, 24 | blocks: Vec, 25 | max_chars: usize, 26 | point_size: f32, 27 | } 28 | 29 | impl PointText { 30 | //pub fn add_text_block(&mut self, 31 | pub fn add_text_block( 32 | &mut self, 33 | font: &font::TextureFont, 34 | position: &[f32; 3], 35 | capacity: usize, 36 | text: &str, 37 | ) -> usize { 38 | if text.chars().count() > capacity { 39 | panic!("text won't fit into capacity for this TextBlock"); 40 | } 41 | let start = match self.blocks.last() { 42 | Some(blk) => blk.start + blk.capacity, 43 | _ => 0, // it must have been an empty Vec 44 | }; 45 | if (start + capacity) > self.max_chars { 46 | panic!("TextBlock is going to overflow PointText"); 47 | } 48 | let new_block = TextBlock { 49 | x: position[0], 50 | y: position[1], 51 | z: position[2], 52 | capacity, 53 | size: 0.99, 54 | text: text.to_string(), 55 | rot: 0.0, 56 | char_rot: 0.0, 57 | spacing: 'F', 58 | space: 0.05, 59 | rgba: [0.999; 4], 60 | justification: 0.0, 61 | start, 62 | }; 63 | self.blocks.push(new_block); 64 | let block_id = self.blocks.len() - 1; 65 | self.regen(font, block_id); 66 | block_id 67 | } 68 | 69 | pub fn draw(&mut self) { 70 | self.points.draw(); 71 | } 72 | 73 | pub fn set_shader(&mut self, shader: &shader::Program) { 74 | self.points.set_shader(shader); 75 | } 76 | 77 | // these all apply to one of the TextBlocks 78 | //pub fn set_position(&mut self, 79 | pub fn set_position( 80 | &mut self, 81 | font: &font::TextureFont, 82 | block_id: usize, 83 | position: &[f32; 3], 84 | ) { 85 | self.blocks[block_id].x = position[0]; 86 | self.blocks[block_id].y = position[1]; 87 | self.blocks[block_id].z = position[2]; 88 | 89 | self.regen(font, block_id); 90 | } 91 | 92 | //pub fn set_text(&mut self, 93 | pub fn set_text(&mut self, font: &font::TextureFont, block_id: usize, text: &str) { 94 | let start = self.blocks[block_id].start; 95 | let capacity = self.blocks[block_id].capacity; 96 | let end = start + capacity; 97 | if text.chars().count() >= capacity { 98 | panic!("text won't fit into capacity for this TextBlock"); 99 | } 100 | for i in start..end { 101 | // set alpha to zero first 102 | self.points.buf[0].array_buffer[[i, 5]] = 0.0; 103 | } 104 | self.blocks[block_id].text = text.to_string(); 105 | self.regen(font, block_id); 106 | } 107 | 108 | //pub fn set_rgba(&mut self, 109 | pub fn set_rgba(&mut self, font: &font::TextureFont, block_id: usize, rgba: &[f32; 4]) { 110 | self.blocks[block_id].rgba = *rgba; 111 | self.regen(font, block_id); 112 | } 113 | 114 | pub fn set_rot(&mut self, font: &font::TextureFont, block_id: usize, rot: f32) { 115 | self.blocks[block_id].rot = rot; 116 | self.regen(font, block_id); 117 | } 118 | 119 | pub fn set_char_rot( 120 | &mut self, 121 | font: &font::TextureFont, 122 | block_id: usize, 123 | char_rot: f32, 124 | ) { 125 | self.blocks[block_id].char_rot = char_rot; 126 | self.regen(font, block_id); 127 | } 128 | 129 | pub fn set_spacing( 130 | &mut self, 131 | font: &font::TextureFont, 132 | block_id: usize, 133 | spacing: char, 134 | ) { 135 | self.blocks[block_id].spacing = spacing; 136 | self.regen(font, block_id); 137 | } 138 | 139 | pub fn set_justification( 140 | &mut self, 141 | font: &font::TextureFont, 142 | block_id: usize, 143 | justification: f32, 144 | ) { 145 | self.blocks[block_id].justification = justification; 146 | self.regen(font, block_id); 147 | } 148 | 149 | pub fn set_size(&mut self, font: &font::TextureFont, block_id: usize, size: f32) { 150 | self.blocks[block_id].size = size; 151 | self.regen(font, block_id); 152 | } 153 | 154 | pub fn set_space(&mut self, font: &font::TextureFont, block_id: usize, space: f32) { 155 | self.blocks[block_id].space = space; 156 | self.regen(font, block_id); 157 | } 158 | 159 | //fn regen(&mut self, block_id: usize) { 160 | fn regen(&mut self, font: &font::TextureFont, block_id: usize) { 161 | //position, rotation etc 162 | let blk = &self.blocks[block_id]; // alias for brevity 163 | let const_w = match blk.spacing { 164 | 'M' => 0.0, 165 | _ => font.size * blk.size * blk.space, 166 | }; 167 | let vari_w = match blk.spacing { 168 | 'M' => blk.size * blk.space, 169 | 'F' => blk.size, 170 | _ => 0.0, 171 | }; 172 | let default = &font.glyph_table[&' ']; 173 | let mut offset = 0.0; 174 | let mut n_char = 0usize; // used for second loop 175 | let g_scale = self.point_size / font.height; 176 | for c in blk.text.chars() { 177 | let glyph = match &font.glyph_table.get(&c) { 178 | &Some(g) => g, 179 | _ => default, 180 | }; 181 | let vi = blk.start + n_char; // index within array_buffer 182 | self.points.buf[0].array_buffer[[vi, 0]] = offset; 183 | self.points.buf[0].array_buffer[[vi, 1]] = glyph.verts[2][1] * g_scale * blk.size; 184 | self.points.buf[0].array_buffer[[vi, 2]] = (blk.z * 10.0).trunc() + blk.size.fract(); 185 | self.points.buf[0].array_buffer[[vi, 3]] = blk.rot + blk.char_rot; 186 | self.points.buf[0].array_buffer[[vi, 4]] = 187 | (blk.rgba[0] * 1000.0).trunc() + blk.rgba[1] * 0.999; 188 | self.points.buf[0].array_buffer[[vi, 5]] = 189 | (blk.rgba[2] * 1000.0).trunc() + blk.rgba[3] * 0.999; 190 | self.points.buf[0].array_buffer[[vi, 6]] = glyph.x; // uv positions 191 | self.points.buf[0].array_buffer[[vi, 7]] = glyph.y; 192 | if blk.spacing == 'F' { 193 | //char centre to right 194 | offset += glyph.w * g_scale * blk.size * 0.5; 195 | } 196 | offset += glyph.w * g_scale * vari_w + const_w; 197 | n_char += 1; 198 | } 199 | let x_off = blk.justification * offset; 200 | let sin_r = blk.rot.sin(); 201 | let cos_r = blk.rot.cos(); 202 | for i in 0..n_char { 203 | let vi = blk.start + i; 204 | let old_x = self.points.buf[0].array_buffer[[vi, 0]] - x_off; 205 | let old_y = self.points.buf[0].array_buffer[[vi, 1]]; 206 | self.points.buf[0].array_buffer[[vi, 0]] = blk.x + old_x * cos_r - old_y * sin_r; 207 | self.points.buf[0].array_buffer[[vi, 1]] = blk.y + old_x * sin_r + old_y * cos_r; 208 | } 209 | self.points.buf[0].re_init(); 210 | } 211 | } 212 | 213 | pub fn create( 214 | cam: Rc>, 215 | font: &font::TextureFont, 216 | max_chars: usize, 217 | point_size: f32, 218 | ) -> PointText { 219 | let verts: Vec = vec![0.0; max_chars * 3]; 220 | let mut new_shape = shapes::points::create(cam, &verts, point_size); 221 | new_shape.buf[0].set_textures(&vec![font.tex.id]); 222 | new_shape.buf[0].set_blend(true); 223 | new_shape.unif[[16, 0]] = 0.05; //TODO base on point_size and 224 | PointText { 225 | points: new_shape, 226 | blocks: vec![], 227 | max_chars, 228 | point_size, 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /pi3d/src/shapes/points.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, buffer, shader}; 5 | 6 | pub fn create( 7 | cam: Rc>, 8 | verts: &[f32], 9 | point_size: f32, 10 | ) -> shape::Shape { 11 | //TODO sort out reason for extra vertex (uv point) 12 | let nverts = verts.len() / 3; 13 | let nfaces = nverts / 3 + 1; 14 | let mut faces = Vec::::new(); 15 | for a in 0..nfaces { 16 | for i in 0..3 { 17 | let v = a * 3 + i; 18 | faces.push(if v < nverts { v } else { nverts - 1 } as u16); 19 | } 20 | } 21 | let norms = nd::Array2::::zeros((nverts, 3)); 22 | let tex_coords = nd::Array2::::zeros((nverts, 2)); 23 | 24 | let mut new_buffer = buffer::create( 25 | &shader::Program::new(), 26 | nd::Array::from_shape_vec((nverts, 3usize), verts.to_vec()).unwrap(), //TODO make functions return Result and feedback errors 27 | norms, 28 | tex_coords, 29 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 30 | false, 31 | ); 32 | 33 | new_buffer.set_point_size(point_size); 34 | 35 | shape::create(vec![new_buffer], cam) 36 | } 37 | -------------------------------------------------------------------------------- /pi3d/src/shapes/sphere.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::f32::consts; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, shapes}; 5 | 6 | pub fn create( 7 | cam: Rc>, 8 | radius: f32, 9 | slices: usize, 10 | sides: usize, 11 | hemi: f32, 12 | invert: bool, 13 | ) -> shape::Shape { 14 | let mut path = Vec::<[f32; 2]>::new(); 15 | // extra points added at poles to reduce distortion (mainly normals) 16 | let st = ((consts::PI - 0.002) * (1.0 - hemi)) / slices as f32; // angular step 17 | path.push([0.0, radius]); 18 | for r in 0..(slices + 1) { 19 | path.push([ 20 | radius * (0.001 + st * r as f32).sin(), 21 | radius * (0.001 + st * r as f32).cos(), 22 | ]); 23 | } 24 | path.push([ 25 | radius * (0.002 + st * slices as f32).sin(), 26 | radius * (0.002 + st * slices as f32).cos(), 27 | ]); 28 | if invert { 29 | path.reverse(); 30 | } 31 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 32 | } 33 | -------------------------------------------------------------------------------- /pi3d/src/shapes/string.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, buffer, shader}; 5 | use crate::util::font; 6 | 7 | const GAP: f32 = 1.0; // line spacing 8 | const SPACE: f32 = 0.03; // between char (proportion of line space) 9 | const NORMALS: [[f32; 3]; 4] = [[0.0, 0.0, -1.0]; 4]; 10 | 11 | pub fn create( 12 | cam: Rc>, 13 | font: &font::TextureFont, 14 | string: &str, 15 | justify: f32, 16 | ) -> shape::Shape { 17 | //TODO sort out reason for extra vertex (uv point) 18 | let mut verts = Vec::::new(); 19 | let mut norms = Vec::::new(); 20 | let mut tex_coords = Vec::::new(); 21 | let mut faces = Vec::::new(); 22 | 23 | let mut xoff = 0.0; 24 | let mut yoff = 0.0; 25 | let nlines = string.matches('\n').count() + 1; 26 | let default = &font.glyph_table[&' ']; 27 | let mut temp_verts = Vec::<[f32; 3]>::new(); 28 | let mut lines = 0; 29 | let sx = 0.24 * 4.0; //TODO pass size argument? 30 | let sy = 0.24 * 4.0; 31 | let mut maxx = -10000.0; 32 | let mut minx = 10000.0; 33 | let mut maxy = -10000.0; 34 | let mut miny = 10000.0; 35 | 36 | let last_char = string.chars().count() - 1; 37 | for (i, c) in string.chars().enumerate() { 38 | if c != '\n' { 39 | let glyph = match &font.glyph_table.get(&c) { 40 | &Some(g) => g, 41 | _ => default, 42 | }; 43 | //let (w, h, texc, verts) = glyph[0:4] 44 | for j in glyph.verts.iter() { 45 | temp_verts.push([j[0] + xoff, j[1], j[2]]); 46 | } 47 | xoff += glyph.w + SPACE * font.height; 48 | for j in glyph.uv.iter() { 49 | tex_coords.push(j[0]); 50 | tex_coords.push(j[1]); 51 | } 52 | for j in NORMALS.iter() { 53 | for k in j.iter() { 54 | norms.push(*k); 55 | } 56 | } 57 | //# Take Into account unprinted \n characters 58 | let stv = 4 * (i - lines) as u16; 59 | faces.push(stv); 60 | faces.push(stv + 1); 61 | faces.push(stv + 2); 62 | faces.push(stv + 2); 63 | faces.push(stv + 3); 64 | faces.push(stv); 65 | } 66 | if i == last_char || c == '\n' { 67 | let cx = xoff * justify; 68 | for temp_vert in &temp_verts { 69 | let x = (temp_vert[0] - cx) * sx; 70 | let y = (temp_vert[1] + nlines as f32 * font.height * GAP / 2.0 - yoff) * sy; 71 | let z = temp_vert[2]; 72 | if x < minx { 73 | minx = x; 74 | } 75 | if x > maxx { 76 | maxx = x; 77 | } 78 | if y < miny { 79 | miny = y; 80 | } 81 | if y > maxy { 82 | maxy = y; 83 | } 84 | verts.push(x); 85 | verts.push(y); 86 | verts.push(z); 87 | } 88 | yoff += font.height * GAP; 89 | xoff = 0.0; 90 | temp_verts.clear(); 91 | lines += 1; 92 | continue; //don't attempt to draw this character! 93 | } 94 | } 95 | verts.append(&mut vec![0.0; 3]); //TODO why needs extra tex coord? 96 | norms.append(&mut vec![0.0; 3]); 97 | tex_coords.append(&mut vec![0.0; 2]); 98 | 99 | let nverts = verts.len() / 3; 100 | let nfaces = faces.len() / 3; 101 | let av_x = (maxx + minx) * 0.5; 102 | let av_y = (maxy + miny) * 0.5; 103 | for i in 0..nverts { 104 | verts[i * 3] -= av_x; // shift x values 105 | verts[i * 3 + 1] -= av_y; // shift y values and flip 106 | } 107 | let mut new_buffer = buffer::create( 108 | &shader::Program::new(), 109 | nd::Array::from_shape_vec((nverts, 3usize), verts).unwrap(), //TODO make functions return Result and feedback errors 110 | nd::Array::from_shape_vec((nverts, 3usize), norms).unwrap(), 111 | nd::Array::from_shape_vec((nverts, 2usize), tex_coords).unwrap(), 112 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 113 | false, 114 | ); 115 | new_buffer.set_textures(&vec![font.tex.id]); 116 | new_buffer.set_blend(true); 117 | shape::create(vec![new_buffer], cam) 118 | } 119 | -------------------------------------------------------------------------------- /pi3d/src/shapes/tcone.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | use crate::{camera, shape, shapes}; 4 | 5 | pub fn create( 6 | cam: Rc>, 7 | radius_bot: f32, 8 | radius_top: f32, 9 | height: f32, 10 | sides: usize, 11 | ) -> shape::Shape { 12 | let path: Vec<[f32; 2]> = vec![ 13 | [0.0, height * 0.5], 14 | [radius_top * 0.999, height * 0.5], 15 | [radius_top, height * 0.5], 16 | [radius_top, height * 0.499], 17 | [radius_bot, -height * 0.499], 18 | [radius_bot, -height * 0.5], 19 | [radius_bot * 0.999, -height * 0.5], 20 | [0.0, -height * 0.5], 21 | ]; 22 | 23 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 24 | } 25 | -------------------------------------------------------------------------------- /pi3d/src/shapes/torus.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::f32::consts; 3 | use std::rc::Rc; 4 | use crate::{camera, shape, shapes}; 5 | 6 | pub fn create( 7 | cam: Rc>, 8 | radius: f32, 9 | thickness: f32, 10 | ringrots: usize, 11 | sides: usize, 12 | ) -> shape::Shape { 13 | let st = consts::PI * 2.0 / ringrots as f32; 14 | let path: Vec<[f32; 2]> = (0..=ringrots) 15 | .map(|i| { 16 | let r = st * i as f32; 17 | [radius - thickness * r.cos(), thickness * r.sin()] 18 | }) 19 | .collect(); 20 | 21 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 22 | } 23 | -------------------------------------------------------------------------------- /pi3d/src/shapes/tube.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use std::cell::RefCell; 3 | use std::f32::consts; 4 | use std::rc::Rc; 5 | use crate::{camera, shape, shapes, buffer, shader}; 6 | 7 | pub fn create( 8 | cam: Rc>, 9 | radius: f32, 10 | thickness: f32, 11 | height: f32, 12 | sides: usize, 13 | use_lathe: bool, 14 | ) -> shape::Shape { 15 | let t = thickness * 0.5; 16 | if use_lathe { 17 | let path: Vec<[f32; 2]> = vec![ 18 | [radius - t * 0.999, height * 0.5], 19 | [radius + t * 0.999, height * 0.5], 20 | [radius + t, height * 0.5], 21 | [radius + t, height * 0.4999], 22 | [radius + t, -height * 0.4999], 23 | [radius + t, -height * 0.5], 24 | [radius + t * 0.999, -height * 0.5], 25 | [radius - t * 0.999, -height * 0.5], 26 | [radius - t, -height * 0.5], 27 | [radius - t, -height * 0.499], 28 | [radius - t, height * 0.499], 29 | [radius - t, height * 0.5], 30 | ]; 31 | 32 | shapes::lathe::create(cam, path, sides, 0.0, 1.0) 33 | } else { 34 | let step = consts::PI * 2.0 / sides as f32; 35 | let otr = radius + t; 36 | let inr = radius - t; 37 | let ht = height * 0.5; 38 | let mut verts = Vec::::new(); 39 | let mut norms = Vec::::new(); 40 | let mut uvs = Vec::::new(); 41 | let mut faces = Vec::::new(); 42 | 43 | let normdirs: [[f32; 2]; 4] = [ 44 | [0.0, 1.0], //up 45 | [1.0, 0.0], //out 46 | [0.0, -1.0], //down 47 | [-1.0, 0.0], 48 | ]; //in 49 | for i in 0..=sides { 50 | for (j, (xz, y)) in [ 51 | (inr, ht), 52 | (otr, ht), // up 53 | (otr, ht), 54 | (otr, -ht), // out 55 | (otr, -ht), 56 | (inr, -ht), // down 57 | (inr, -ht), 58 | (inr, ht), 59 | ] 60 | .iter() 61 | .enumerate() 62 | { 63 | // in 64 | let s = (i as f32 * step).sin(); 65 | let c = (i as f32 * step).cos(); 66 | verts.extend_from_slice(&[xz * s, *y, xz * c]); 67 | let k: usize = j / 2; 68 | norms.extend_from_slice(&[normdirs[k][0] * s, normdirs[k][1], normdirs[k][0] * c]); 69 | if k == 0 || k == 2 { 70 | // top or bottom 71 | uvs.extend_from_slice(&[ 72 | 0.5 * (1.0 + verts[j * 3] / otr), 73 | 0.5 * (1.0 + verts[j * 3 + 2] / otr), 74 | ]); 75 | } else { 76 | uvs.extend_from_slice(&[i as f32 / sides as f32, 0.5 * (1.0 + y / ht)]); 77 | } 78 | } 79 | if i < sides { 80 | for (a, b, c) in [ 81 | (0, 1, 8), 82 | (1, 9, 8), 83 | (2, 3, 10), 84 | (3, 11, 10), 85 | (4, 5, 12), 86 | (12, 5, 13), 87 | (6, 7, 14), 88 | (7, 15, 14), 89 | ] 90 | .iter() 91 | { 92 | let f_off = 8 * i as u16; 93 | faces.extend_from_slice(&[a + f_off, b + f_off, c + f_off]); 94 | } 95 | } 96 | } 97 | let nverts = verts.len() / 3; 98 | let nfaces = faces.len() / 3; 99 | let new_buffer = buffer::create( 100 | &shader::Program::new(), 101 | nd::Array::from_shape_vec((nverts, 3usize), verts).unwrap(), //TODO make functions return Result and feedback errors 102 | nd::Array::from_shape_vec((nverts, 3usize), norms).unwrap(), 103 | nd::Array::from_shape_vec((nverts, 2usize), uvs).unwrap(), 104 | nd::Array::from_shape_vec((nfaces, 3usize), faces).unwrap(), 105 | false, 106 | ); 107 | shape::create(vec![new_buffer], cam) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /pi3d/src/texture.rs: -------------------------------------------------------------------------------- 1 | use crate::image::GenericImageView; 2 | use gl::types::*; 3 | use ndarray as nd; 4 | use crate::util::resources; 5 | 6 | pub struct Texture { 7 | pub id: GLuint, 8 | pub image: nd::Array3, 9 | pub width: usize, 10 | pub height: usize, 11 | pub repeat: GLint, 12 | } 13 | 14 | impl Texture { 15 | pub fn update_ndarray(&mut self) { 16 | let (h, w, d) = self.image.dim(); 17 | let c_type = match d { 18 | 1 => gl::RED, 19 | 2 => gl::RG, 20 | 3 => gl::RGB, 21 | _ => gl::RGBA, //TODO catching other types such as 5_6_5 or 4_4_4_4 22 | }; 23 | unsafe { 24 | gl::BindTexture(gl::TEXTURE_2D, self.id); 25 | 26 | gl::TexParameteri( 27 | gl::TEXTURE_2D, 28 | gl::TEXTURE_MIN_FILTER, 29 | gl::LINEAR_MIPMAP_NEAREST as GLint, 30 | ); 31 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); 32 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, self.repeat); 33 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, self.repeat); 34 | gl::TexImage2D( 35 | gl::TEXTURE_2D, 36 | 0, 37 | c_type as GLint, 38 | w as GLint, 39 | h as GLint, 40 | 0, 41 | c_type, 42 | gl::UNSIGNED_BYTE, 43 | self.image.as_ptr() as *const GLvoid, 44 | ); 45 | gl::Enable(gl::TEXTURE_2D); 46 | gl::GenerateMipmap(gl::TEXTURE_2D); 47 | } 48 | } 49 | 50 | pub fn flip_image(&mut self, vert: bool, horizontal: bool) { 51 | let v = if vert { -1 } else { 1 }; 52 | let h = if horizontal { -1 } else { 1 }; 53 | self.image = self.image.slice(s![..;v, ..;h, ..]).to_owned(); 54 | self.update_ndarray(); 55 | } 56 | 57 | pub fn size(&mut self) -> (usize, usize) { 58 | let (h, w, _d) = self.image.dim(); 59 | (w, h) 60 | } 61 | 62 | pub fn set_mirrored_repeat(&mut self, on: bool) { 63 | self.repeat = if on { gl::MIRRORED_REPEAT } else { gl::REPEAT } as GLint; 64 | self.update_ndarray(); 65 | } 66 | } 67 | 68 | impl Drop for Texture { 69 | fn drop(&mut self) { 70 | print!("-tex{:?} ", self.id); 71 | unsafe { 72 | gl::BindTexture(gl::TEXTURE, 0); 73 | gl::DeleteTextures(1, &self.id); 74 | } 75 | } 76 | } 77 | 78 | pub fn create_from_array(image: nd::Array3) -> Texture { 79 | let mut new_id: GLuint = 0; 80 | unsafe { 81 | gl::GenTextures(1, &mut new_id); 82 | } 83 | let (height, width, _d) = image.dim(); 84 | let mut tex = Texture { 85 | id: new_id, 86 | image, 87 | width, 88 | height, 89 | repeat: gl::REPEAT as GLint, 90 | }; 91 | tex.update_ndarray(); 92 | tex 93 | } 94 | 95 | pub fn create_from_file(name: &str) -> Texture { 96 | let pb = resources::resource_name_to_path(name); 97 | let im = image::open(pb).unwrap(); 98 | let (w, h) = im.dimensions(); 99 | let c_type: usize = match im.color() { 100 | image::ColorType::Gray(_u8) => 1, 101 | image::ColorType::GrayA(_u8) => 2, 102 | image::ColorType::RGB(_u8) => 3, 103 | image::ColorType::RGBA(_u8) => 4, 104 | _ => 4, // TODO catch unrecognised types, need to cope with indexed 105 | }; 106 | let image = 107 | nd::Array::from_shape_vec((h as usize, w as usize, c_type), im.raw_pixels()).unwrap(); 108 | create_from_array(image) 109 | } 110 | -------------------------------------------------------------------------------- /pi3d/src/util/font.rs: -------------------------------------------------------------------------------- 1 | use ndarray as nd; 2 | use rusttype::{point, Font, Scale}; 3 | use std::collections::HashMap; 4 | use std::fs::File; 5 | use std::io::Read; 6 | use crate::util::resources; 7 | use crate::texture; 8 | 9 | const TEX_SZ: usize = 1024; 10 | 11 | pub struct GlyphTable { 12 | pub w: f32, 13 | pub h: f32, 14 | pub uv: [[f32; 2]; 4], 15 | pub verts: [[f32; 3]; 4], 16 | pub x: f32, // 17 | pub y: f32, 18 | } 19 | 20 | pub struct TextureFont { 21 | pub tex: texture::Texture, 22 | pub glyph_table: HashMap, 23 | pub height: f32, 24 | pub size: f32, 25 | } 26 | 27 | pub fn create(file_name: &str, glyphs: &str, add_glyphs: &str, size: f32) -> TextureFont { 28 | let grid_n = TEX_SZ / (size as usize); //TODO magic numbers! 29 | // Load the font 30 | let path_buf = resources::resource_name_to_path(file_name); 31 | let mut f = File::open(path_buf).expect("file not found"); 32 | let mut contents = Vec::new(); 33 | f.read_to_end(&mut contents) 34 | .expect("something went wrong reading the file"); 35 | let font = Font::from_bytes(contents).expect("Error constructing Font"); 36 | 37 | let mut image = nd::Array3::::zeros((TEX_SZ, TEX_SZ, 4)); 38 | 39 | let scale = Scale { x: size, y: size }; 40 | //TODO space needed 41 | let glyph_list = if glyphs.is_empty() { 42 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`1234567890-=~!@#$%^&*()_+[]\\{}|;':,./<>?\"" 43 | } else { 44 | glyphs 45 | }; 46 | let glyph_list = [glyph_list, add_glyphs].concat(); 47 | 48 | let f_v_metrics = font.v_metrics(scale); 49 | let v_step = f_v_metrics.ascent - f_v_metrics.descent; // +ve is up here! 50 | //println!("{:?}", f_v_metrics); 51 | let mut cpoint = point(size * 0.5, size); 52 | //let mut advance = 0.0; 53 | let mut glyph_table = HashMap::::new(); 54 | // put in a space as no pixel_bounding_box 55 | glyph_table.insert( 56 | ' ', 57 | GlyphTable { 58 | w: size * 0.2, 59 | h: 1.0, 60 | uv: [[0.01, 0.0], [0.0, 0.0], [0.0, 0.01], [0.01, 0.01]], 61 | verts: [ 62 | [0.01, 0.0, 0.0], 63 | [0.0, 0.0, 0.0], 64 | [0.0, -0.01, 0.0], 65 | [0.01, -0.01, 0.0], 66 | ], 67 | x: 0.0, 68 | y: 0.01, 69 | }, 70 | ); 71 | for (i, c) in glyph_list.chars().enumerate() { 72 | let g = font.glyph(c); 73 | let g = g.scaled(scale); 74 | if let Some(g_b_box) = g.exact_bounding_box() { 75 | // only do this if there's a glyph 76 | cpoint.x = 77 | ((i + 1) % grid_n) as f32 * size + (size - g_b_box.max.x - g_b_box.min.x) * 0.5; 78 | cpoint.y = ((i + 1) / grid_n + 1) as f32 * size; //TODO magic numbers 79 | let g = g.positioned(cpoint); 80 | if let Some(p_b_box) = g.pixel_bounding_box() { 81 | //TODO error catching 82 | g.draw(|x, y, v| { 83 | let px = (x + p_b_box.min.x as u32) as usize; 84 | let py = (y + p_b_box.min.y as u32) as usize; 85 | for j in 0..3 { 86 | image[[py, px, j]] = 255; 87 | } 88 | image[[py, px, 3]] = (v * 255.0) as u8; 89 | }); 90 | let cwidth = g_b_box.max.x - g_b_box.min.x; 91 | let cheight = g_b_box.max.y - g_b_box.min.y; 92 | let xscl = (cpoint.x + g_b_box.min.x) / TEX_SZ as f32; 93 | let yscl = (cpoint.y + g_b_box.min.y) / TEX_SZ as f32; 94 | let tw = cwidth / TEX_SZ as f32; 95 | let th = cheight / TEX_SZ as f32; 96 | let gt = GlyphTable { 97 | w: cwidth, 98 | h: cheight, 99 | uv: [ 100 | [xscl + tw, yscl + th], 101 | [xscl, yscl + th], 102 | [xscl, yscl], 103 | [xscl + tw, yscl], 104 | ], 105 | verts: [ 106 | [cwidth, -g_b_box.max.y, 0.0], 107 | [0.0, -g_b_box.max.y, 0.0], 108 | [0.0, cheight - g_b_box.max.y, 0.0], 109 | [cwidth, cheight - g_b_box.max.y, 0.0], 110 | ], 111 | x: xscl, 112 | y: yscl, 113 | }; 114 | glyph_table.insert(c, gt); 115 | } 116 | } 117 | } 118 | let tex = texture::create_from_array(image); 119 | TextureFont { 120 | tex, 121 | glyph_table, 122 | height: v_step, 123 | size, 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /pi3d/src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod font; 2 | pub mod offscreen_texture; 3 | pub mod post_process; 4 | pub mod resources; 5 | pub mod vec3; 6 | pub mod vec4; 7 | -------------------------------------------------------------------------------- /pi3d/src/util/offscreen_texture.rs: -------------------------------------------------------------------------------- 1 | use gl::types::*; 2 | use crate::display; 3 | 4 | pub struct OffscreenTexture { 5 | pub color_tex_id: GLuint, 6 | pub depth_tex_id: GLuint, 7 | pub width: usize, 8 | pub height: usize, 9 | pub framebuffer: GLuint, 10 | pub depthbuffer: GLuint, 11 | } 12 | 13 | impl OffscreenTexture { 14 | /// 15 | pub fn start(&mut self, clear: bool) { 16 | unsafe { 17 | gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer); 18 | gl::BindRenderbuffer(gl::RENDERBUFFER, self.depthbuffer); 19 | gl::RenderbufferStorage( 20 | gl::RENDERBUFFER, 21 | gl::DEPTH_COMPONENT16, 22 | self.width as GLsizei, 23 | self.height as GLsizei, 24 | ); 25 | gl::FramebufferRenderbuffer( 26 | gl::FRAMEBUFFER, 27 | gl::DEPTH_ATTACHMENT, 28 | gl::RENDERBUFFER, 29 | self.depthbuffer, 30 | ); 31 | gl::FramebufferTexture2D( 32 | gl::FRAMEBUFFER, 33 | gl::COLOR_ATTACHMENT0, 34 | gl::TEXTURE_2D, 35 | self.color_tex_id, 36 | 0, 37 | ); 38 | gl::BindTexture(gl::TEXTURE_2D, 0); // this seems to be needed here 39 | gl::FramebufferTexture2D( 40 | gl::FRAMEBUFFER, 41 | gl::DEPTH_ATTACHMENT, 42 | gl::TEXTURE_2D, 43 | self.depth_tex_id, 44 | 0, 45 | ); 46 | if clear { 47 | // TODO allow just depth or just color clearing? 48 | gl::Clear(gl::DEPTH_BUFFER_BIT | gl::COLOR_BUFFER_BIT); 49 | } 50 | } 51 | //TODO global offscreen queue - check why needed. 52 | } 53 | /// 54 | pub fn end(&self) { 55 | unsafe { 56 | gl::BindTexture(gl::TEXTURE_2D, 0); 57 | gl::BindFramebuffer(gl::FRAMEBUFFER, 0); 58 | } 59 | //TODO offscreen queue? 60 | } 61 | /// 62 | pub fn delete_buffers(&mut self) { 63 | unsafe { 64 | gl::DeleteFramebuffers(1, &self.framebuffer); 65 | gl::DeleteRenderbuffers(1, &self.depthbuffer); 66 | gl::BindTexture(gl::TEXTURE, 0); 67 | gl::DeleteTextures(1, &self.color_tex_id); 68 | gl::DeleteTextures(1, &self.depth_tex_id); 69 | } 70 | } 71 | } 72 | /// 73 | impl Drop for OffscreenTexture { 74 | fn drop(&mut self) { 75 | print!("-ost{:?}.{:?} ", self.color_tex_id, self.depth_tex_id); 76 | self.delete_buffers(); 77 | } 78 | } 79 | 80 | /// 81 | pub fn create(display: &display::Display) -> OffscreenTexture { 82 | let height = display.height as usize; 83 | let width = display.width as usize; 84 | let mut color_tex_id: GLuint = 0; 85 | let mut depth_tex_id: GLuint = 0; 86 | unsafe { 87 | gl::GenTextures(1, &mut color_tex_id); 88 | gl::BindTexture(gl::TEXTURE_2D, color_tex_id); 89 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint); 90 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); 91 | gl::TexParameteri( 92 | gl::TEXTURE_2D, 93 | gl::TEXTURE_WRAP_S, 94 | gl::CLAMP_TO_EDGE as GLint, 95 | ); 96 | gl::TexParameteri( 97 | gl::TEXTURE_2D, 98 | gl::TEXTURE_WRAP_T, 99 | gl::CLAMP_TO_EDGE as GLint, 100 | ); 101 | gl::TexImage2D( 102 | gl::TEXTURE_2D, 103 | 0, 104 | gl::RGBA as GLint, 105 | width as GLint, 106 | height as GLint, 107 | 0, 108 | gl::RGBA, 109 | gl::UNSIGNED_BYTE, 110 | std::ptr::null() as *const GLvoid, 111 | ); 112 | gl::GenerateMipmap(gl::TEXTURE_2D); 113 | gl::BindTexture(gl::TEXTURE_2D, 0); 114 | 115 | gl::GenTextures(1, &mut depth_tex_id); 116 | gl::BindTexture(gl::TEXTURE_2D, depth_tex_id); 117 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint); 118 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint); 119 | gl::TexParameteri( 120 | gl::TEXTURE_2D, 121 | gl::TEXTURE_WRAP_S, 122 | gl::CLAMP_TO_EDGE as GLint, 123 | ); 124 | gl::TexParameteri( 125 | gl::TEXTURE_2D, 126 | gl::TEXTURE_WRAP_T, 127 | gl::CLAMP_TO_EDGE as GLint, 128 | ); 129 | gl::TexImage2D( 130 | gl::TEXTURE_2D, 131 | 0, 132 | gl::DEPTH_COMPONENT16 as GLint, 133 | width as GLint, 134 | height as GLint, 135 | 0, 136 | gl::DEPTH_COMPONENT, 137 | gl::UNSIGNED_SHORT, 138 | std::ptr::null() as *const GLvoid, 139 | ); 140 | gl::GenerateMipmap(gl::TEXTURE_2D); 141 | gl::BindTexture(gl::TEXTURE_2D, 0); 142 | gl::Enable(gl::TEXTURE_2D); 143 | } 144 | let mut framebuffer: GLuint = 0; 145 | let mut depthbuffer: GLuint = 0; 146 | unsafe { 147 | gl::GenFramebuffers(1, &mut framebuffer); 148 | gl::GenRenderbuffers(1, &mut depthbuffer); 149 | } 150 | OffscreenTexture { 151 | color_tex_id, 152 | depth_tex_id, 153 | width, 154 | height, 155 | framebuffer, 156 | depthbuffer, 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /pi3d/src/util/post_process.rs: -------------------------------------------------------------------------------- 1 | use gl::types::*; 2 | 3 | use std::cell::RefCell; 4 | use std::rc::Rc; 5 | use crate::util::offscreen_texture; 6 | use crate::{shape, camera, shapes, display, shader}; 7 | 8 | pub struct PostProcess { 9 | pub offscreen_texture: offscreen_texture::OffscreenTexture, 10 | pub sprite: shape::Shape, 11 | pub scale: f32, 12 | } 13 | 14 | impl PostProcess { 15 | /// 16 | pub fn start_capture(&mut self, clear: bool) { 17 | self.offscreen_texture.start(clear); 18 | let width = self.offscreen_texture.width as f32; 19 | let height = self.offscreen_texture.height as f32; 20 | //if self.scale != 1.0 { 21 | let xx = (width / 2.0 * (1.0 - self.scale)) as GLint; 22 | let yy = (height / 2.0 * (1.0 - self.scale)) as GLint; 23 | let ww = (width * self.scale) as GLint; 24 | let hh = (height * self.scale) as GLint; 25 | unsafe { 26 | gl::Enable(gl::SCISSOR_TEST); 27 | gl::Scissor(xx, yy, ww, hh); 28 | } 29 | //} 30 | } 31 | /// 32 | pub fn end_capture(&mut self) { 33 | self.offscreen_texture.end(); 34 | //if self.scale != 1.0 { 35 | unsafe { 36 | gl::Disable(gl::SCISSOR_TEST); 37 | } 38 | //} 39 | } 40 | /// 41 | pub fn draw(&mut self, unif_vals: Vec<(usize, usize, f32)>) { 42 | for (i, j, val) in unif_vals { 43 | self.sprite.unif[[i, j]] = val; 44 | } 45 | self.sprite.draw(); 46 | } 47 | } 48 | 49 | pub fn create( 50 | cam: Rc>, 51 | display: &display::Display, 52 | shader: &shader::Program, 53 | add_tex: &[GLuint], 54 | scale: f32, 55 | ) -> PostProcess { 56 | let offscreen_texture = offscreen_texture::create(display); 57 | let mut sprite = shapes::plane::create(cam, display.width, display.height); 58 | sprite.buf[0].unib[[2, 0]] = scale; 59 | sprite.buf[0].unib[[2, 1]] = scale; 60 | sprite.buf[0].unib[[3, 0]] = (1.0 - scale) * 0.5; 61 | sprite.buf[0].unib[[3, 1]] = (1.0 - scale) * 0.5; 62 | sprite.buf[0].textures = vec![ 63 | offscreen_texture.color_tex_id, 64 | offscreen_texture.depth_tex_id, 65 | ]; 66 | sprite.buf[0].textures.extend(add_tex); 67 | sprite.buf[0].set_shader(shader); 68 | sprite.position_z(20.0); 69 | PostProcess { 70 | offscreen_texture, 71 | sprite, 72 | scale, 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pi3d/src/util/resources.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::io::{self, Read}; 3 | use std::path::PathBuf; 4 | 5 | use crate::shaders::built_in_shaders::{CODES, NAMES}; 6 | use crate::{EXE_PATH, CURRENT_DIR}; 7 | 8 | #[derive(Debug)] 9 | pub enum Error { 10 | Io(io::Error), 11 | FileContainsNil, 12 | FailedToGetExePath, 13 | MissingResource, 14 | RecursionDepth, 15 | WindowBuildError { name: String }, 16 | } 17 | 18 | impl From for Error { 19 | fn from(other: io::Error) -> Self { 20 | Error::Io(other) 21 | } 22 | } 23 | 24 | pub fn load_string(resource_name: &str) -> Result { 25 | let mut listing = Vec::::new(); 26 | load_includes(resource_name, &mut listing, 0)?; 27 | Ok(listing.join("\n")) 28 | } 29 | /* 30 | pub fn resource_name_to_path(location: &str) -> PathBuf { 31 | let new_path = PathBuf::from(location); 32 | let mut path = PathBuf::new(); 33 | if !new_path.has_root() { // only start from exe root path if not / 34 | path = (*EXE_PATH).to_path_buf(); //why does it need this (clone says it's a Path) 35 | } 36 | path.join(new_path) 37 | } 38 | */ 39 | pub fn resource_name_to_path(location: &str) -> PathBuf { 40 | //let new_path = PathBuf::from(location); 41 | let mut exe_path = (*EXE_PATH).to_path_buf(); 42 | exe_path.push(location); 43 | let mut cur_path = (*CURRENT_DIR).to_path_buf(); 44 | cur_path.push(location); 45 | if cur_path.is_file() { 46 | return cur_path; 47 | } 48 | if exe_path.is_file() { 49 | return exe_path; 50 | } 51 | if cur_path.is_dir() { 52 | return cur_path; 53 | } 54 | exe_path 55 | } 56 | 57 | fn load_includes(resource_name: &str, listing: &mut Vec, depth: u32) -> Result<(), Error> { 58 | if depth > 16 { 59 | return Err(Error::RecursionDepth); 60 | } 61 | let mut text_chunk = String::new(); 62 | for (i, name) in NAMES.iter().enumerate() { 63 | // first try built_in_shaders 64 | if *name == resource_name.trim() { 65 | text_chunk = CODES[i].to_string(); 66 | break; 67 | } 68 | } 69 | if text_chunk.is_empty() { 70 | // now check file path 71 | let path_buf = resource_name_to_path(resource_name); 72 | if !path_buf.is_file() { 73 | return Err(Error::MissingResource); 74 | } // nope 75 | let mut file = fs::File::open(path_buf).unwrap(); 76 | file.read_to_string(&mut text_chunk)?; 77 | } 78 | if text_chunk.is_empty() { 79 | return Err(Error::MissingResource); // still not got anything so stop now 80 | } 81 | for s in (&text_chunk).lines() { 82 | match s.find("#include") { 83 | Some(ix) => { 84 | let (_, new_key) = s.split_at(ix + 9); 85 | load_includes(new_key, listing, depth + 1)?; 86 | } 87 | None => { 88 | listing.push(s.to_string()); 89 | } 90 | } 91 | } 92 | Ok(()) 93 | } 94 | -------------------------------------------------------------------------------- /pi3d/src/util/vec3.rs: -------------------------------------------------------------------------------- 1 | /* utility functions working with 1D vectors of xyz f32 values using ndarray::arr1 2 | */ 3 | extern crate ndarray; 4 | 5 | use ndarray as nd; 6 | 7 | pub fn add(a: &nd::Array1, b: &nd::Array1) -> nd::Array1 { 8 | a + b 9 | } 10 | 11 | pub fn sub(a: &nd::Array1, b: &nd::Array1) -> nd::Array1 { 12 | a - b 13 | } 14 | 15 | pub fn len(a: &nd::Array1) -> f32 { 16 | let len: f32 = a.iter().map(|x| x * x).sum(); 17 | len.sqrt() 18 | } 19 | 20 | pub fn norm(a: &nd::Array1) -> nd::Array1 { 21 | let len = len(a); 22 | if len == 0.0 { 23 | return nd::arr1(&[0.0, 1.0, 0.0]); 24 | } 25 | a / len 26 | } 27 | 28 | pub fn dot(a: &nd::Array1, b: &nd::Array1) -> f32 { 29 | (a * b).sum() // ndarray has .dot() 30 | } 31 | 32 | pub fn cross(a: &nd::Array1, b: &nd::Array1) -> nd::Array1 { 33 | nd::arr1(&[ 34 | a[1] * b[2] - a[2] * b[1], 35 | a[2] * b[0] - a[0] * b[2], 36 | a[0] * b[1] - a[1] * b[0], 37 | ]) 38 | } 39 | 40 | pub fn rotate_vec(a: &[f32; 3], vecs: &nd::Array2) -> nd::Array2 { 41 | rotate_vec_slice(a, &vecs.slice(s![.., ..])) 42 | } 43 | pub fn rotate_vec_slice(a: &[f32; 3], vecs: &nd::ArrayView2) -> nd::Array2 { 44 | let (cx, sx) = (a[0].cos(), a[0].sin()); 45 | let (cy, sy) = (a[1].cos(), a[1].sin()); 46 | let (cz, sz) = (a[2].cos(), a[2].sin()); 47 | let rx = nd::arr2(&[[1.0, 0.0, 0.0], [0.0, cx, sx], [0.0, -sx, cx]]); 48 | let ry = nd::arr2(&[[cy, 0.0, -sy], [0.0, 1.0, 0.0], [sy, 0.0, cy]]); 49 | let rz = nd::arr2(&[[cz, sz, 0.0], [-sz, cz, 0.0], [0.0, 0.0, 1.0]]); 50 | rz.dot(&rx.dot(&ry.dot(&vecs.reversed_axes()))) 51 | .reversed_axes() 52 | } 53 | 54 | /// normalize a 3 column wide slice of an array in place. 55 | /// 56 | /// NB in order for this to be able to work on a slice of an array it 57 | /// requires the lefthand colum 'from' to be supplied as an argument 58 | pub fn normalize_slice(vecs: &mut nd::Array2, from: usize) { 59 | let n = vecs.shape()[0]; 60 | for i in 0..n { 61 | let len: f32 = vecs 62 | .slice(s![i, from..(from + 3)]) 63 | .iter() 64 | .map(|x| x * x) 65 | .sum(); 66 | if len > 0.0 { 67 | let len_inv = 1.0 / len.sqrt(); 68 | for j in from..(from + 3) { 69 | vecs[[i, j]] *= len_inv; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /pi3d/src/util/vec4.rs: -------------------------------------------------------------------------------- 1 | /* utility functions working with 1D vectors of xyz f32 values using ndarray::arr1 2 | */ 3 | extern crate ndarray; 4 | 5 | use ndarray as nd; 6 | 7 | /// invert a 4x4 matrix TODO not used at the moment 8 | fn _inv_matrix(m: &nd::Array2) -> nd::Array2 { 9 | let a2323 = m[[2, 2]] * m[[3, 3]] - m[[2, 3]] * m[[3, 2]]; 10 | let a1323 = m[[2, 1]] * m[[3, 3]] - m[[2, 3]] * m[[3, 1]]; 11 | let a1223 = m[[2, 1]] * m[[3, 2]] - m[[2, 2]] * m[[3, 1]]; 12 | let a0323 = m[[2, 0]] * m[[3, 3]] - m[[2, 3]] * m[[3, 0]]; 13 | let a0223 = m[[2, 0]] * m[[3, 2]] - m[[2, 2]] * m[[3, 0]]; 14 | let a0123 = m[[2, 0]] * m[[3, 1]] - m[[2, 1]] * m[[3, 0]]; 15 | let a2313 = m[[1, 2]] * m[[3, 3]] - m[[1, 3]] * m[[3, 2]]; 16 | let a1313 = m[[1, 1]] * m[[3, 3]] - m[[1, 3]] * m[[3, 1]]; 17 | let a1213 = m[[1, 1]] * m[[3, 2]] - m[[1, 2]] * m[[3, 1]]; 18 | let a2312 = m[[1, 2]] * m[[2, 3]] - m[[1, 3]] * m[[2, 2]]; 19 | let a1312 = m[[1, 1]] * m[[2, 3]] - m[[1, 3]] * m[[2, 1]]; 20 | let a1212 = m[[1, 1]] * m[[2, 2]] - m[[1, 2]] * m[[2, 1]]; 21 | let a0313 = m[[1, 0]] * m[[3, 3]] - m[[1, 3]] * m[[3, 0]]; 22 | let a0213 = m[[1, 0]] * m[[3, 2]] - m[[1, 2]] * m[[3, 0]]; 23 | let a0312 = m[[1, 0]] * m[[2, 3]] - m[[1, 3]] * m[[2, 0]]; 24 | let a0212 = m[[1, 0]] * m[[2, 2]] - m[[1, 2]] * m[[2, 0]]; 25 | let a0113 = m[[1, 0]] * m[[3, 1]] - m[[1, 1]] * m[[3, 0]]; 26 | let a0112 = m[[1, 0]] * m[[2, 1]] - m[[1, 1]] * m[[2, 0]]; 27 | 28 | let det = 1.0f32 29 | / (m[[0, 0]] * (m[[1, 1]] * a2323 - m[[1, 2]] * a1323 + m[[1, 3]] * a1223) 30 | - m[[0, 1]] * (m[[1, 0]] * a2323 - m[[1, 2]] * a0323 + m[[1, 3]] * a0223) 31 | + m[[0, 2]] * (m[[1, 0]] * a1323 - m[[1, 1]] * a0323 + m[[1, 3]] * a0123) 32 | - m[[0, 3]] * (m[[1, 0]] * a1223 - m[[1, 1]] * a0223 + m[[1, 2]] * a0123)); 33 | 34 | nd::arr2(&[ 35 | [ 36 | det * (m[[1, 1]] * a2323 - m[[1, 2]] * a1323 + m[[1, 3]] * a1223), 37 | det * -(m[[0, 1]] * a2323 - m[[0, 2]] * a1323 + m[[0, 3]] * a1223), 38 | det * (m[[0, 1]] * a2313 - m[[0, 2]] * a1313 + m[[0, 3]] * a1213), 39 | det * -(m[[0, 1]] * a2312 - m[[0, 2]] * a1312 + m[[0, 3]] * a1212), 40 | ], 41 | [ 42 | det * -(m[[1, 0]] * a2323 - m[[1, 2]] * a0323 + m[[1, 3]] * a0223), 43 | det * (m[[0, 0]] * a2323 - m[[0, 2]] * a0323 + m[[0, 3]] * a0223), 44 | det * -(m[[0, 0]] * a2313 - m[[0, 2]] * a0313 + m[[0, 3]] * a0213), 45 | det * (m[[0, 0]] * a2312 - m[[0, 2]] * a0312 + m[[0, 3]] * a0212), 46 | ], 47 | [ 48 | det * (m[[1, 0]] * a1323 - m[[1, 1]] * a0323 + m[[1, 3]] * a0123), 49 | det * -(m[[0, 0]] * a1323 - m[[0, 1]] * a0323 + m[[0, 3]] * a0123), 50 | det * (m[[0, 0]] * a1313 - m[[0, 1]] * a0313 + m[[0, 3]] * a0113), 51 | det * -(m[[0, 0]] * a1312 - m[[0, 1]] * a0312 + m[[0, 3]] * a0112), 52 | ], 53 | [ 54 | det * -(m[[1, 0]] * a1223 - m[[1, 1]] * a0223 + m[[1, 2]] * a0123), 55 | det * (m[[0, 0]] * a1223 - m[[0, 1]] * a0223 + m[[0, 2]] * a0123), 56 | det * -(m[[0, 0]] * a1213 - m[[0, 1]] * a0213 + m[[0, 2]] * a0113), 57 | det * (m[[0, 0]] * a1212 - m[[0, 1]] * a0212 + m[[0, 2]] * a0112), 58 | ], 59 | ]) 60 | } 61 | -------------------------------------------------------------------------------- /pyo3_module/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2024" 3 | name = "rpi3d" 4 | version = "0.1.0" 5 | authors = ["paddywwof "] 6 | 7 | [lib] 8 | name = "rpi3d" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | numpy = "0.22" 13 | ndarray = "0.16" 14 | pi3d = {path = "../pi3d"} 15 | gl = "^0.10" 16 | 17 | [dependencies.pyo3] 18 | version = "0.22" 19 | features = ["extension-module"] 20 | 21 | [profile.release] 22 | codegen-units = 1 23 | incremental = true -------------------------------------------------------------------------------- /pyo3_module/README.md: -------------------------------------------------------------------------------- 1 | Start of an attempt to make a python wrapper for rust_pi3d using pyo3. 2 | You should be able to compile the module either: 3 | 4 | in pyo3_module run ``python3 setup.py bdist_wheel`` then open the 5 | whl file in ``dist`` and extract ``rpi3d/rpi3d-0.1....so`` to the 6 | ``pyo3_module/test`` directory. You should be able to run test1.py 7 | 8 | or: 9 | 10 | in pyo3_module run ``cargo build --release`` then copy and rename 11 | ``librpi3d.so`` to ``pyo3_module/test/rpi3d.so`` 12 | 13 | ~~NB you must use nightly for pyo3 ``rustup install nightly`` then 14 | ``rust default nightly``, switch back with ``rustup default stable``~~ Works 15 | using stable rust now. 16 | -------------------------------------------------------------------------------- /pyo3_module/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | try: 4 | from setuptools_rust import RustExtension 5 | except ImportError: 6 | import subprocess 7 | import sys 8 | 9 | errno = subprocess.call([sys.executable, "-m", "pip", "install", "setuptools-rust", "--user"]) 10 | if errno: 11 | print("Please install setuptools-rust package") 12 | raise SystemExit(errno) 13 | else: 14 | from setuptools_rust import RustExtension 15 | 16 | setup_requires = ['setuptools-rust>=0.10.2'] 17 | #install_requires = ['numpy'] 18 | 19 | setup( 20 | name='rpi3d', 21 | version='0.1.0', 22 | description='Python wrapper on rust_pi3d using pyo3', 23 | rust_extensions=[RustExtension( 24 | 'rpi3d.rpi3d', 25 | './Cargo.toml', 26 | )], 27 | #install_requires=install_requires, 28 | setup_requires=setup_requires, 29 | packages=find_packages(), 30 | zip_safe=False, 31 | ) -------------------------------------------------------------------------------- /pyo3_module/src/core.rs: -------------------------------------------------------------------------------- 1 | use pyo3::exceptions; 2 | use pyo3::prelude::*; 3 | use pyo3::PyObject; //, PyRawObject}; 4 | 5 | use numpy::{IntoPyArray, PyArray3}; 6 | 7 | use std::cell::RefCell; 8 | use std::rc::Rc; 9 | use crate::{util, shapes}; 10 | 11 | #[pyclass(unsendable)] // think SDL requires this to stay in main thread 12 | pub struct Display { 13 | pub r_display: Rc>, 14 | } 15 | 16 | #[pymethods] 17 | impl Display { 18 | #[new] 19 | #[args( 20 | name = "\"\"", 21 | w = "0.0", 22 | h = "0.0", 23 | profile = "\"GLES\"", 24 | major = "2", 25 | minor = "0" 26 | )] 27 | fn new(name: &str, w: f32, h: f32, profile: &str, major: u8, minor: u8) -> Self { 28 | let (wnew, hnew, fullscreen) = if w <= 0.0 || h <= 0.0 { 29 | (100.0, 100.0, true) 30 | } else { 31 | (w, h, false) 32 | }; 33 | /*let dispnew = Arc::new(Mutex::new( 34 | pi3d::display::create(name, wnew, hnew, profile, major, minor).unwrap() 35 | ));*/ 36 | let dispnew = Rc::new(RefCell::new( 37 | pi3d::display::create(name, wnew, hnew, profile, major, minor).unwrap(), 38 | )); 39 | if fullscreen { 40 | dispnew.borrow_mut().set_fullscreen(true); 41 | } 42 | Display { r_display: dispnew } 43 | } 44 | 45 | #[staticmethod] 46 | #[args( 47 | name = "\"\"", 48 | w = "0.0", 49 | h = "0.0", 50 | profile = "\"GLES\"", 51 | major = "2", 52 | minor = "0" 53 | )] 54 | fn create( 55 | name: &str, 56 | w: f32, 57 | h: f32, 58 | profile: &str, 59 | major: u8, 60 | minor: u8, 61 | ) -> PyResult> { 62 | let gil = Python::acquire_gil(); 63 | let py = gil.python(); 64 | let (wnew, hnew, fullscreen) = if w <= 0.0 || h <= 0.0 { 65 | (100.0, 100.0, true) 66 | } else { 67 | (w, h, false) 68 | }; 69 | let r_display = Rc::new(RefCell::new( 70 | pi3d::display::create(name, wnew, hnew, profile, major, minor).unwrap(), 71 | )); 72 | if fullscreen { 73 | r_display.borrow_mut().set_fullscreen(true); 74 | } 75 | r_display.borrow_mut().set_target_fps(1000.0); //TODO set to 60; testing run as fast as poss 76 | r_display.borrow_mut().set_mouse_relative(true); 77 | Py::new(py, Display { r_display }) 78 | } 79 | 80 | fn loop_running(&mut self) -> PyResult { 81 | Ok(self.r_display.borrow_mut().loop_running()) 82 | } 83 | } 84 | 85 | /// Camera stuff 86 | /// 87 | #[pyclass(unsendable)] 88 | pub struct Camera { 89 | pub r_camera: pi3d::camera::Camera, 90 | } 91 | 92 | #[pymethods] 93 | impl Camera { 94 | #[new] 95 | fn new(display: &Display) -> Self { 96 | Camera { 97 | r_camera: pi3d::camera::create(&display.r_display.borrow()), 98 | } 99 | } 100 | fn reset(&mut self) { 101 | self.r_camera.reset(); 102 | } 103 | fn set_3d(&mut self, is_3d: bool) { 104 | self.r_camera.set_3d(is_3d); 105 | } 106 | fn position(&mut self, pos: Vec) { 107 | if pos.len() != 3 { 108 | return; 109 | } 110 | self.r_camera.position(&[pos[0], pos[1], pos[2]]); 111 | } 112 | fn rotate(&mut self, rot: Vec) { 113 | if rot.len() != 3 { 114 | return; 115 | } 116 | self.r_camera.rotate(&[rot[0], rot[1], rot[2]]); 117 | } 118 | fn get_direction(&mut self) -> Vec { 119 | self.r_camera.get_direction().to_vec() 120 | } 121 | } 122 | 123 | /// Shader stuff 124 | /// 125 | #[pyclass] 126 | pub struct Shader { 127 | pub r_shader: pi3d::shader::Program, 128 | } 129 | 130 | #[pymethods] 131 | impl Shader { 132 | #[new] 133 | fn new(name: &str) -> Self { 134 | Shader { 135 | r_shader: pi3d::shader::Program::from_res(name).unwrap(), 136 | } 137 | } 138 | } 139 | 140 | /// Keyboard stuff 141 | /// 142 | #[pyclass(unsendable)] 143 | struct Keyboard { 144 | r_display: Rc>, 145 | } 146 | 147 | #[pymethods] 148 | impl Keyboard { 149 | #[new] 150 | fn new(display: &Display) -> Self { 151 | Keyboard { 152 | r_display: display.r_display.clone(), 153 | } 154 | } 155 | /// crude char reading as per pi3d 156 | fn read_code(&self) -> String { 157 | let disp = self.r_display.borrow(); 158 | if disp.keys_pressed.len() > 0 { 159 | return disp.keys_pressed.last().unwrap().name(); 160 | } 161 | "".to_string() 162 | } 163 | } 164 | 165 | /// Mouse stuff 166 | /// 167 | #[pyclass(unsendable)] 168 | struct Mouse { 169 | r_display: Rc>, 170 | } 171 | 172 | #[pymethods] 173 | impl Mouse { 174 | #[new] 175 | fn new(display: &Display) -> Self { 176 | Mouse { 177 | r_display: display.r_display.clone(), 178 | } 179 | } 180 | /// also need velocity, values depend on mouse relative (also visibility of cursor) 181 | fn position(&self) -> (i32, i32) { 182 | let disp = self.r_display.borrow(); 183 | (disp.mouse_x, disp.mouse_y) 184 | } 185 | } 186 | 187 | /// Texture stuff 188 | /// 189 | #[pyclass] 190 | pub struct Texture { 191 | pub r_texture: pi3d::texture::Texture, 192 | } 193 | 194 | #[pymethods] 195 | impl Texture { 196 | #[new] 197 | fn new(file_name: &str) -> Self { 198 | Texture { 199 | r_texture: pi3d::texture::create_from_file(file_name), 200 | } 201 | } 202 | fn print_id(&self) { 203 | println!("texid={}", self.r_texture.id); 204 | } 205 | #[getter] 206 | fn get_image(&mut self) -> PyResult>> { 207 | let gil = pyo3::Python::acquire_gil(); 208 | let py = gil.python(); 209 | Ok(self.r_texture.image.clone().into_pyarray(py).to_owned()) 210 | } 211 | #[setter] 212 | fn set_image(&mut self, im_arr: &PyArray3) -> PyResult<()> { 213 | unsafe { 214 | let new_im_arr = im_arr.as_array().to_owned(); 215 | let new_shape = new_im_arr.shape(); 216 | let old_shape = self.r_texture.image.shape(); 217 | if new_shape[0] != old_shape[0] || new_shape[1] != old_shape[1] { 218 | return Err(PyErr::new::( 219 | "array wrong shape", 220 | )); 221 | } 222 | //TODO fix different 3rd dim size (1,3,4) 223 | self.r_texture.image = new_im_arr; 224 | } 225 | self.r_texture.update_ndarray(); 226 | Ok(()) 227 | } 228 | } 229 | 230 | #[pymodule] 231 | fn rpi3d(_py: Python, m: &PyModule) -> PyResult<()> { 232 | m.add_class::()?; 233 | m.add_class::()?; 234 | m.add_class::()?; 235 | m.add_class::()?; 236 | m.add_class::()?; 237 | m.add_class::()?; 238 | 239 | m.add_class::()?; 240 | m.add_class::()?; 241 | 242 | m.add_class::()?; 243 | m.add_class::()?; 244 | m.add_class::()?; 245 | m.add_class::()?; 246 | m.add_class::()?; 247 | m.add_class::()?; 248 | m.add_class::()?; 249 | m.add_class::()?; 250 | m.add_class::()?; 251 | m.add_class::()?; 252 | m.add_class::()?; 253 | m.add_class::()?; 254 | m.add_class::()?; 255 | m.add_class::()?; 256 | m.add_class::()?; 257 | m.add_class::()?; 258 | m.add_class::()?; 259 | 260 | m.add_class::()?; 261 | Ok(()) 262 | } 263 | -------------------------------------------------------------------------------- /pyo3_module/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate gl; 2 | extern crate numpy; 3 | extern crate pi3d; 4 | extern crate pyo3; 5 | 6 | pub mod core; 7 | pub mod shapes; 8 | pub mod util; 9 | -------------------------------------------------------------------------------- /pyo3_module/src/util.rs: -------------------------------------------------------------------------------- 1 | use pyo3::prelude::*; 2 | use pyo3::PyObject; 3 | use crate::core; 4 | 5 | //use numpy::{IntoPyArray, PyArray3}; 6 | 7 | /// Font stuff 8 | /// 9 | #[pyclass] 10 | pub struct Font { 11 | pub r_font: pi3d::util::font::TextureFont, 12 | } 13 | 14 | #[pymethods] 15 | impl Font { 16 | #[new] 17 | fn new(file_name: &str, glyphs: &str, add_glyphs: &str, size: f32) -> Self { 18 | Font { 19 | r_font: pi3d::util::font::create(file_name, glyphs, add_glyphs, size), 20 | } 21 | } 22 | } 23 | /// PostProcess stuff 24 | /// 25 | #[pyclass(unsendable)] 26 | pub struct PostProcess { 27 | pub r_postprocess: pi3d::util::post_process::PostProcess, 28 | } 29 | 30 | #[pymethods] 31 | impl PostProcess { 32 | #[new] 33 | fn new( 34 | camera: &mut core::Camera, 35 | display: &core::Display, 36 | shader: &core::Shader, 37 | add_tex: Vec>, 38 | scale: f32, 39 | ) -> Self { 40 | let texlist:Vec = add_tex.iter().map(|t| t.r_texture.id).collect(); 41 | PostProcess { 42 | r_postprocess: pi3d::util::post_process::create( 43 | camera.r_camera.reference(), 44 | &display.r_display.borrow(), 45 | &shader.r_shader, 46 | &texlist, 47 | scale, 48 | ), 49 | } 50 | } 51 | pub fn start_capture(&mut self, clear: bool) { 52 | self.r_postprocess.start_capture(clear); 53 | } 54 | pub fn end_capture(&mut self) { 55 | self.r_postprocess.end_capture(); 56 | } 57 | pub fn draw(&mut self, unif_vals: Vec<(usize, usize, f32)>) { 58 | self.r_postprocess.draw(unif_vals); 59 | } 60 | /*#[getter]//don't think this will work! Probably need gl::ReadPixels() 61 | fn get_image(&mut self) -> PyResult>> { 62 | let gil = pyo3::Python::acquire_gil(); 63 | let py = gil.python(); 64 | Ok(self.r_postprocess.offscreen_texture.tex.image 65 | .clone() 66 | .into_pyarray(py) 67 | .to_owned() 68 | ) 69 | }*/ 70 | } 71 | -------------------------------------------------------------------------------- /pyo3_module/test/NotoSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/NotoSerif-Regular.ttf -------------------------------------------------------------------------------- /pyo3_module/test/floor_nm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/floor_nm.jpg -------------------------------------------------------------------------------- /pyo3_module/test/hornbeam2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/hornbeam2.png -------------------------------------------------------------------------------- /pyo3_module/test/mountains3_512.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/mountains3_512.jpg -------------------------------------------------------------------------------- /pyo3_module/test/mountainsHgt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/mountainsHgt.png -------------------------------------------------------------------------------- /pyo3_module/test/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/pattern.png -------------------------------------------------------------------------------- /pyo3_module/test/rpi3d.cpython-37m-arm-linux-gnueabihf.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/rpi3d.cpython-37m-arm-linux-gnueabihf.so -------------------------------------------------------------------------------- /pyo3_module/test/rust_pi3d.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'pi3R.blend' 2 | # Material Count: 6 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | 12 | newmtl black_rust 13 | Ns 225.000000 14 | Ka 1.000000 1.000000 1.000000 15 | Kd 0.009134 0.008023 0.007499 16 | Ks 0.500000 0.500000 0.500000 17 | Ke 0.0 0.0 0.0 18 | Ni 1.450000 19 | d 1.000000 20 | illum 3 21 | 22 | newmtl blue 23 | Ns 225.000000 24 | Ka 1.000000 1.000000 1.000000 25 | Kd 0.034340 0.061246 0.799103 26 | Ks 0.500000 0.500000 0.500000 27 | Ke 0.0 0.0 0.0 28 | Ni 1.450000 29 | d 1.000000 30 | illum 2 31 | 32 | newmtl green 33 | Ns 225.000000 34 | Ka 1.000000 1.000000 1.000000 35 | Kd 0.003347 0.309469 0.010330 36 | Ks 0.500000 0.500000 0.500000 37 | Ke 0.0 0.0 0.0 38 | Ni 1.450000 39 | d 1.000000 40 | illum 2 41 | 42 | newmtl red 43 | Ns 225.000000 44 | Ka 1.000000 1.000000 1.000000 45 | Kd 0.799103 0.000000 0.006512 46 | Ks 0.500000 0.500000 0.500000 47 | Ke 0.0 0.0 0.0 48 | Ni 1.450000 49 | d 1.000000 50 | illum 2 51 | 52 | newmtl yellow 53 | Ns 225.000000 54 | Ka 1.000000 1.000000 1.000000 55 | Kd 0.799103 0.391572 0.004025 56 | Ks 0.500000 0.500000 0.500000 57 | Ke 0.0 0.0 0.0 58 | Ni 1.450000 59 | d 1.000000 60 | illum 2 61 | -------------------------------------------------------------------------------- /pyo3_module/test/sbox_back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_back.jpg -------------------------------------------------------------------------------- /pyo3_module/test/sbox_bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_bottom.jpg -------------------------------------------------------------------------------- /pyo3_module/test/sbox_front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_front.jpg -------------------------------------------------------------------------------- /pyo3_module/test/sbox_left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_left.jpg -------------------------------------------------------------------------------- /pyo3_module/test/sbox_right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_right.jpg -------------------------------------------------------------------------------- /pyo3_module/test/sbox_top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/pyo3_module/test/sbox_top.jpg -------------------------------------------------------------------------------- /pyo3_module/test/test1.py: -------------------------------------------------------------------------------- 1 | import rpi3d 2 | import os 3 | import time 4 | import numpy as np 5 | from PIL import Image 6 | 7 | display = rpi3d.Display.create("pyo3 minimal", w=1920, h=1080, profile="GLES", major=2, minor=0) 8 | shader = rpi3d.Shader("uv_light") 9 | shader_flat = rpi3d.Shader("uv_flat") 10 | shader_mat = rpi3d.Shader("mat_reflect") 11 | shader_post = rpi3d.Shader("post_base") 12 | 13 | keybd = rpi3d.Keyboard(display) 14 | mouse = rpi3d.Mouse(display) 15 | tex = rpi3d.Texture("pattern.png") 16 | tex2 = rpi3d.Texture("mountains3_512.jpg") 17 | ntex = tex.image.copy() 18 | ntex[:64,:,:2] += 64 19 | tex.image = ntex 20 | 21 | camera = rpi3d.Camera(display) 22 | camera2d = rpi3d.Camera(display) 23 | camera2d.set_3d(False) 24 | 25 | plane = rpi3d.Plane(camera, 300.0, 300.0) # NB camera has to be passed to Shape constructor 26 | plane.set_draw_details(shader_flat, [tex]) 27 | plane.position_z(300.0) 28 | 29 | cube = rpi3d.Tube(camera) 30 | cube.set_draw_details(shader, [tex]) 31 | cube.position([-2.0, 8.0, 5.0]) 32 | 33 | sphere = rpi3d.Sphere(camera) 34 | sphere.set_draw_details(shader, [tex]) 35 | sphere.position([0.0, 10.0, 4.0]) 36 | 37 | verts = [[0.0, 2.0], [0.5, 1.9], [0.2, 1.8], [1.0, 0.5], [1.0, 0.4], [0.0, 0.0]] 38 | lathe = rpi3d.Lathe(camera, verts, 16, 0.0, 1.0) 39 | lathe.set_draw_details(shader, [tex]) 40 | lathe.position([2.0, 8.0, 4.0]) 41 | 42 | verts = [-1.0, 2.0, 1.0, -1.2, -0.5, 1.0, -0.2, -0.5, 1.0, 0.0, -1.0, 1.0, 1.5, 0.5, 1.0] 43 | lines = rpi3d.Lines(camera, verts, 5.0, True) 44 | lines.set_draw_details(shader, [tex]) 45 | lines.position([2.0, 12.0, 5.0]) 46 | 47 | points = rpi3d.Points(camera, verts, 40.0) 48 | points.set_draw_details(shader, [tex]) 49 | points.position([-2.0, 12.0, 5.0]) 50 | 51 | font = rpi3d.Font("NotoSerif-Regular.ttf", "", "", 64) 52 | string = rpi3d.PyString(camera2d, font, "Hello from rust pi3d", 0.0) 53 | string.set_shader(shader_flat) 54 | string.position([100.0, 100.0, 4.0]) 55 | 56 | sphere.scale([0.5, 1.5, 0.5]) 57 | sphere.position([1.0, 1.0, 1.0]) 58 | child = rpi3d.RefShape(sphere) 59 | sphere.position([0.0, 10.0, 4.0]) 60 | sphere.scale([0.7, 0.7, 0.7]) 61 | cube.add_child(child) 62 | 63 | terrain = rpi3d.ElevationMap(camera, "mountainsHgt.png", 500.0, 500.0, 20.0, 32, 32, 1.0, "nothing") 64 | terrain.set_draw_details(shader, [tex2]) 65 | terrain.position([0.0, -2.0, 0.0]) 66 | 67 | tree_tex = rpi3d.Texture("hornbeam2.png") 68 | treeplane = rpi3d.Plane(camera, 2.0, 2.0) 69 | treemodel = rpi3d.MergeShape(camera) 70 | treemodel.add_shapes([treeplane, treeplane], [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 1.5, 0.0]], 71 | [[1.0, 2.0, 1.0], [1.0, 2.0, 1.0]], [0, 0]) 72 | trees = rpi3d.MergeShape(camera) 73 | trees.cluster(treemodel, terrain, 50.0, 50.0, 100.0, 50.0, 0.5, 7.5, 100) 74 | trees.set_draw_details(shader_flat, [tree_tex]) 75 | 76 | normtex = rpi3d.Texture("floor_nm.jpg") 77 | model = rpi3d.Model(camera, "rust_pi3d.obj") 78 | model.set_shader(shader_mat) 79 | model.set_normal_shine(normtex=normtex, ntiles=4.0, shinetex=tree_tex, shiny=0.05, bump_factor=0.02) 80 | model.position([-30, 10, 30]) 81 | model.scale([20, 20, 20]) 82 | model.rotate_to_y(-2.5) 83 | 84 | ecube = rpi3d.EnvironmentCube(camera, 900, "sbox", "jpg") 85 | ecube.set_shader(shader_flat) 86 | 87 | n=0 88 | tm = time.time() 89 | (mx, my) = (0, 0) 90 | (rot, tilt) = (0, 0) 91 | (x, y, z) = (0, 0, 0) 92 | ds = 0.01 93 | while display.loop_running(): 94 | string.draw() 95 | string.rotate_inc_z(0.001) 96 | 97 | plane.draw() 98 | plane.rotate_inc_z(0.001) 99 | 100 | cube.draw() 101 | child.rotate_inc_y(0.01) 102 | cube.rotate_inc_z(0.0017) 103 | cube.rotate_inc_x(0.0021) 104 | cube.rotate_inc_y(0.0001) 105 | 106 | sphere.draw() 107 | sphere.rotate_inc_z(0.001) 108 | sphere.rotate_inc_x(0.0021) 109 | sphere.rotate_inc_y(0.007) 110 | if n % 50 == 0: 111 | pb = sphere.array_buffer.copy() 112 | pb[:,:3] *= np.random.random((len(pb), 3)) * 0.01 + 0.995 113 | sphere.array_buffer = pb 114 | 115 | lathe.draw() 116 | lathe.rotate_inc_z(0.001) 117 | lathe.rotate_inc_x(0.0021) 118 | lathe.rotate_inc_y(0.0011) 119 | 120 | lines.draw() 121 | lines.rotate_inc_z(0.001) 122 | lines.rotate_inc_x(0.0021) 123 | lines.rotate_inc_y(0.0011) 124 | 125 | points.draw() 126 | points.rotate_inc_z(0.001) 127 | points.rotate_inc_x(0.0021) 128 | points.rotate_inc_y(0.0011) 129 | 130 | model.draw() 131 | 132 | trees.draw() 133 | 134 | terrain.draw() 135 | 136 | ecube.draw() 137 | 138 | n += 1 139 | k = keybd.read_code() 140 | if len(k) > 0: 141 | if k == 'W': 142 | ds = 0.25 143 | elif k == 'S': 144 | ds = -0.07 145 | 146 | (new_mx, new_my) = (mouse.position()) 147 | if new_mx != mx or new_my != my or ds != 0.0: 148 | (mx, my) = (new_mx, new_my) 149 | tilt = (my - 300.0) * -0.004 150 | rot = (mx - 400.0) * -0.004 151 | camera.reset() 152 | camera.rotate([tilt, rot, 0.0]) 153 | 154 | if ds != 0.0: 155 | cd = camera.get_direction() 156 | x += cd[0] * ds 157 | y += cd[1] * ds 158 | z += cd[2] * ds 159 | (newy, _mapnorm) = terrain.calc_height(x, z) 160 | y = newy + 0.0 161 | camera.position([x, y, z]) 162 | ds = 0.0 ## to trick camera setting to terrail 163 | 164 | print("{:.1f} FPS".format(n / (time.time() - tm))) 165 | -------------------------------------------------------------------------------- /pyo3_module/test/test2.py: -------------------------------------------------------------------------------- 1 | import rpi3d 2 | import os 3 | import time 4 | import numpy as np 5 | from PIL import Image 6 | 7 | display = rpi3d.Display.create("pyo3 minimal", w=800, h=600, profile="GLES", major=2, minor=0) 8 | shader = rpi3d.Shader("uv_light") 9 | shader_flat = rpi3d.Shader("uv_flat") 10 | shader_post = rpi3d.Shader("post_base") 11 | 12 | keybd = rpi3d.Keyboard(display) 13 | mouse = rpi3d.Mouse(display) 14 | tex = rpi3d.Texture("pattern.png") 15 | tex2 = rpi3d.Texture("mountains3_512.jpg") 16 | 17 | camera = rpi3d.Camera(display) 18 | camera2d = rpi3d.Camera(display) 19 | camera2d.set_3d(False) 20 | 21 | plane = rpi3d.Plane(camera, 300.0, 300.0) # NB camera has to be passed to Shape constructor 22 | plane.set_draw_details(shader_flat, [tex]) 23 | plane.position_z(300.0) 24 | 25 | cube = rpi3d.Tube(camera) 26 | cube.set_draw_details(shader, [tex]) 27 | cube.position([-2.0, 8.0, 5.0]) 28 | 29 | sphere = rpi3d.Sphere(camera) 30 | sphere.set_draw_details(shader, [tex]) 31 | sphere.position([0.0, 10.0, 4.0]) 32 | 33 | verts = [[0.0, 2.0], [0.5, 1.9], [0.2, 1.8], [1.0, 0.5], [1.0, 0.4], [0.0, 0.0]] 34 | lathe = rpi3d.Lathe(camera, verts, 16, 0.0, 1.0) 35 | lathe.set_draw_details(shader, [tex]) 36 | lathe.position([2.0, 8.0, 4.0]) 37 | 38 | verts = [-1.0, 2.0, 1.0, -1.2, -0.5, 1.0, -0.2, -0.5, 1.0, 0.0, -1.0, 1.0, 1.5, 0.5, 1.0] 39 | lines = rpi3d.Lines(camera, verts, 5.0, True) 40 | lines.set_draw_details(shader, [tex]) 41 | lines.position([2.0, 12.0, 5.0]) 42 | 43 | points = rpi3d.Points(camera, verts, 40.0) 44 | points.set_draw_details(shader, [tex]) 45 | points.position([-2.0, 12.0, 5.0]) 46 | 47 | font = rpi3d.Font("NotoSerif-Regular.ttf", "", "", 64) 48 | string = rpi3d.PyString(camera2d, font, "Hello from rust pi3d", 0.0) 49 | string.set_shader(shader_flat) 50 | string.position([100.0, 100.0, 4.0]) 51 | 52 | terrain = rpi3d.ElevationMap(camera, "mountainsHgt.png", 500.0, 500.0, 20.0, 32, 32, 1.0, "nothing") 53 | terrain.set_draw_details(shader, [tex2]) 54 | terrain.position([0.0, -2.0, 0.0]) 55 | 56 | post = rpi3d.PostProcess(camera2d, display, shader_post, [], 1.0) 57 | 58 | n=0 59 | tm = time.time() 60 | (mx, my) = (0, 0) 61 | (rot, tilt) = (0, 0) 62 | (x, y, z) = (0, 0, 0) 63 | ds = 0.01 64 | while display.loop_running(): 65 | string.draw() 66 | string.rotate_inc_z(0.001) 67 | 68 | post.start_capture(True) 69 | plane.draw() 70 | plane.rotate_inc_z(0.001) 71 | 72 | cube.draw() 73 | cube.rotate_inc_z(0.0017) 74 | cube.rotate_inc_x(0.0021) 75 | cube.rotate_inc_y(0.0001) 76 | 77 | sphere.draw() 78 | sphere.rotate_inc_z(0.001) 79 | sphere.rotate_inc_x(0.0021) 80 | sphere.rotate_inc_y(0.007) 81 | 82 | lathe.draw() 83 | lathe.rotate_inc_z(0.001) 84 | lathe.rotate_inc_x(0.0021) 85 | lathe.rotate_inc_y(0.0011) 86 | 87 | lines.draw() 88 | lines.rotate_inc_z(0.001) 89 | lines.rotate_inc_x(0.0021) 90 | lines.rotate_inc_y(0.0011) 91 | 92 | points.draw() 93 | points.rotate_inc_z(0.001) 94 | points.rotate_inc_x(0.0021) 95 | points.rotate_inc_y(0.0011) 96 | 97 | terrain.draw() 98 | 99 | post.end_capture() 100 | 101 | n += 1 102 | k = keybd.read_code() 103 | if len(k) > 0: 104 | if k == 'W': 105 | ds = 0.25 106 | elif k == 'S': 107 | ds = -0.07 108 | 109 | (new_mx, new_my) = (mouse.position()) 110 | if new_mx != mx or new_my != my or ds != 0.0: 111 | (mx, my) = (new_mx, new_my) 112 | tilt = (my - 300.0) * -0.004 113 | rot = (mx - 400.0) * -0.004 114 | camera.reset() 115 | camera.rotate([tilt, rot, 0.0]) 116 | 117 | if ds != 0.0: 118 | cd = camera.get_direction() 119 | x += cd[0] * ds 120 | y += cd[1] * ds 121 | z += cd[2] * ds 122 | (newy, _mapnorm) = terrain.calc_height(x, z) 123 | y = newy + 0.0 124 | camera.position([x, y, z]) 125 | ds = 0.0 ## to trick camera setting to terrail 126 | f = (tilt + rot) * 0.2 + (400 + x + y + z) * 0.01 127 | f = abs(f % 10.0 - 5.0) # triangular rather than saw-tooth 128 | post.draw([(16, 0, f), (16, 1, 0.0), (16, 2, 0.0)]) 129 | 130 | print("{:.1f} FPS".format(n / (time.time() - tm))) -------------------------------------------------------------------------------- /pyo3_module/test/test3.py: -------------------------------------------------------------------------------- 1 | import rpi3d 2 | import os 3 | import time 4 | 5 | display = rpi3d.Display.create("pyo3 minimal", w=800, h=600, profile="GLES", major=2, minor=0) 6 | shader = rpi3d.Shader("uv_light") 7 | shader_flat = rpi3d.Shader("uv_flat") 8 | shader_blur = rpi3d.Shader("defocus") 9 | 10 | keybd = rpi3d.Keyboard(display) 11 | mouse = rpi3d.Mouse(display) 12 | tex = rpi3d.Texture("pattern.png") 13 | tex2 = rpi3d.Texture("mountains3_512.jpg") 14 | 15 | camera = rpi3d.Camera(display) 16 | camera2d = rpi3d.Camera(display) 17 | camera2d.set_3d(False) 18 | 19 | cube = rpi3d.Tube(camera) 20 | cube.position([-4.0, 7.0, 2.0]) 21 | cube.set_draw_details(shader, [tex]) 22 | 23 | sphere = rpi3d.Sphere(camera) 24 | sphere.position([-3.0, 8.0, 3.0]) 25 | sphere.set_draw_details(shader, [tex]) 26 | 27 | font = rpi3d.Font("NotoSerif-Regular.ttf", "", "", 64) 28 | string = rpi3d.PyString(camera2d, font, "Hello from rust pi3d", 0.0) 29 | string.set_shader(shader_flat) 30 | string.position([100.0, 100.0, 4.0]) 31 | 32 | terrain = rpi3d.ElevationMap(camera, "mountainsHgt.png", 500.0, 500.0, 20.0, 32, 32, 1.0, "nothing") 33 | terrain.set_draw_details(shader, [tex2]) 34 | terrain.position([0.0, -2.0, 0.0]) 35 | 36 | defocus = rpi3d.PostProcess(camera2d, display, shader_blur, [], 1.0) 37 | 38 | n=0 39 | tm = time.time() 40 | (mx, my) = (0, 0) 41 | (rot, tilt) = (0, 0) 42 | (x, y, z) = (0, 0, 0) 43 | ds = 0.01 44 | while display.loop_running(): 45 | 46 | #string.draw() 47 | #string.rotate_inc_z(0.001) 48 | 49 | defocus.start_capture(True) 50 | 51 | terrain.draw() 52 | 53 | cube.draw() 54 | cube.rotate_inc_z(0.0017) 55 | cube.rotate_inc_x(0.0021) 56 | cube.rotate_inc_y(0.0001) 57 | 58 | sphere.draw() 59 | sphere.rotate_inc_z(0.001) 60 | sphere.rotate_inc_x(0.0021) 61 | sphere.rotate_inc_y(0.007) 62 | 63 | defocus.end_capture() 64 | 65 | n += 1 66 | k = keybd.read_code() 67 | if len(k) > 0: 68 | if k == 'W': 69 | ds = 0.25 70 | elif k == 'S': 71 | ds = -0.07 72 | 73 | (new_mx, new_my) = mouse.position() 74 | if new_mx != mx or new_my != my or ds != 0.0: 75 | (mx, my) = (new_mx, new_my) 76 | tilt = (my - 300.0) * -0.004 77 | rot = (mx - 400.0) * -0.004 78 | camera.reset() 79 | camera.rotate([tilt, rot, 0.0]) 80 | 81 | if ds != 0.0: 82 | cd = camera.get_direction() 83 | x += cd[0] * ds 84 | y += cd[1] * ds 85 | z += cd[2] * ds 86 | (newy, _mapnorm) = terrain.calc_height(x, z) 87 | y = newy + 0.0 88 | camera.position([x, y, z]) 89 | ds = 0.0 ## to trick camera setting to terrail 90 | 91 | defocus.draw([(14, 0, 0.7), (14, 1, 0.1), (14, 2, 0.003)]) 92 | 93 | 94 | print("{:.1f} FPS".format(n / (time.time() - tm))) -------------------------------------------------------------------------------- /rust_pi3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paddywwoof/rust_pi3d/de7e673c1c18751cf95a5bf48aeb74ca33d3fb47/rust_pi3d.png --------------------------------------------------------------------------------