Some basic shading; textures now supported in the Utmyen model format
Getty Ritter
9 years ago
| 4 | 4 | authors = ["Getty Ritter <gdritter@galois.com>"] |
| 5 | 5 | |
| 6 | 6 | [dependencies] |
| 7 | image = "*" | |
| 7 | 8 | glium = "*" |
| 163 | 163 | } |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | pub fn as_bytes(&self) -> Result<Vec<u8>, String> { | |
| 167 | match self { | |
| 168 | &Bencode::Str(ref bs) => Ok(bs.clone()), | |
| 169 | _ => fail("not a string"), | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 166 | 173 | pub fn map<A, F>(&self, func: F) -> Result<Vec<A>, String> |
| 167 | 174 | where F: 'static + Fn(&Bencode) -> Result<A, String> |
| 168 | 175 | { |
| 1 | 1 | extern crate core; |
| 2 | 2 | #[macro_use] |
| 3 | 3 | extern crate glium; |
| 4 | extern crate image; | |
| 4 | 5 | |
| 5 | 6 | // mod adnot; |
| 6 | 7 | mod bencode; |
| 9 | 10 | use glium::{DisplayBuild, Program, Surface}; |
| 10 | 11 | use glium::glutin::Event; |
| 11 | 12 | use glium::glutin::WindowBuilder; |
| 12 | ||
| 13 | // use bencode::Bencode; | |
| 13 | use glium::texture::Texture2d; | |
| 14 | 14 | |
| 15 | 15 | fn sample() -> model::Model { |
| 16 | 16 | let file = std::env::args().nth(1) |
| 18 | 18 | model::Model::load_from_file(&file).unwrap() |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn sample_texture(display: &glium::Display) -> Texture2d { | |
| 22 | use std::io::Cursor; | |
| 23 | let img = image::load(Cursor::new(&include_bytes!("/home/gdritter/pictures/cube-uv.png")[..]), | |
| 24 | image::PNG).unwrap().to_rgba(); | |
| 25 | let dims = img.dimensions(); | |
| 26 | let img = glium::texture::RawImage2d::from_raw_rgba_reversed(img.into_raw(), dims); | |
| 27 | Texture2d::new(display, img).unwrap() | |
| 28 | } | |
| 29 | ||
| 21 | 30 | const VERTEX_SHADER: &'static str = r#" |
| 22 | 31 | #version 140 |
| 32 | ||
| 23 | 33 | in vec3 pos; |
| 34 | in vec3 nrm; | |
| 35 | in vec2 tex; | |
| 24 | 36 | |
| 25 | 37 | uniform mat4 perspective; |
| 26 | 38 | uniform mat4 matrix; |
| 27 | 39 | |
| 28 |
out vec3 o_ |
|
| 40 | out vec3 o_nrm; | |
| 41 | out vec2 o_tex; | |
| 29 | 42 | |
| 30 | 43 | void main() { |
| 31 |
o_ |
|
| 44 | o_nrm = transpose(inverse(mat3(matrix))) * nrm; | |
| 45 | o_tex = tex; | |
| 32 | 46 | gl_Position = perspective * matrix * vec4(pos, 1.0); |
| 33 | 47 | } |
| 34 | 48 | "#; |
| 35 | 49 | |
| 36 | 50 | const FRAGMENT_SHADER: &'static str = r#" |
| 37 | 51 | #version 140 |
| 38 | in vec3 o_pos; | |
| 52 | ||
| 53 | in vec3 o_nrm; | |
| 54 | in vec2 o_tex; | |
| 55 | ||
| 56 | uniform vec3 u_light; | |
| 57 | uniform sampler2D tex; | |
| 58 | ||
| 39 | 59 | out vec4 color; |
| 60 | ||
| 40 | 61 | void main() { |
| 41 |
|
|
| 62 | float brightness = dot(normalize(o_nrm), normalize(u_light)); | |
| 63 | float factor = 0.5 + (brightness * 0.5); | |
| 64 | color = texture(tex, o_tex) * factor; | |
| 42 | 65 | } |
| 43 | 66 | "#; |
| 44 | 67 | |
| 49 | 72 | .with_depth_buffer(24) |
| 50 | 73 | .build_glium() |
| 51 | 74 | .unwrap(); |
| 75 | ||
| 52 | 76 | let vbuf = md.get_vbuf(&display); |
| 53 | 77 | let idxs = md.get_ibuf(&display); |
| 78 | let tx = md.get_tex(&display).unwrap_or(sample_texture(&display)); | |
| 79 | ||
| 54 | 80 | let program = Program::from_source( |
| 55 | 81 | &display, |
| 56 | 82 | VERTEX_SHADER, |
| 57 | 83 | FRAGMENT_SHADER, |
| 58 | 84 | None).unwrap(); |
| 59 | 85 | |
| 86 | let light = [-1.0, 0.4, 0.9f32]; | |
| 60 | 87 | let mut px = 0f32; |
| 61 | 88 | let mut py = 0.02f32; |
| 89 | let mut pz = 0.0f32; | |
| 62 | 90 | let mut rt = 0f32; |
| 63 | 91 | let dx = 0.001; |
| 64 | 92 | let sx = 0.01f32; |
| 86 | 114 | |
| 87 | 115 | let uniforms = uniform! { |
| 88 | 116 | perspective: perspective, |
| 117 | u_light: light, | |
| 118 | tex: &tx, | |
| 89 | 119 | matrix: [ [ rt.cos() * sx, 0.0, -rt.sin() * sx, 0.0 ], |
| 90 | 120 | [ 0.0, sx, 0.0, 0.0 ], |
| 91 | 121 | [ rt.sin() * sx, 0.0, rt.cos() * sx, 0.0 ], |
| 92 |
[ px, |
|
| 122 | [ px, pz, py, sx ] | |
| 93 | 123 | ] |
| 94 | 124 | }; |
| 95 | 125 | |
| 113 | 143 | for ev in display.poll_events() { |
| 114 | 144 | match ev { |
| 115 | 145 | Event::Closed => return, |
| 116 | Event::KeyboardInput(_, 9, _) => return, | |
| 117 | Event::KeyboardInput(_, 24, _) => { | |
| 118 | rt -= 0.1; | |
| 119 | }, | |
| 120 | Event::KeyboardInput(_, 25, _) => { | |
| 121 | py -= dx; | |
| 122 | }, | |
| 123 | Event::KeyboardInput(_, 26, _) => { | |
| 124 | rt += 0.1; | |
| 125 | }, | |
| 126 | Event::KeyboardInput(_, 38, _) => { | |
| 127 | px -= dx; | |
| 128 | }, | |
| 129 | Event::KeyboardInput(_, 39, _) => { | |
| 130 | py += dx; | |
| 131 | }, | |
| 132 | Event::KeyboardInput(_, 40, _) => { | |
| 133 | px += dx; | |
| 134 | }, | |
| 135 | evt => { | |
| 136 |
|
|
| 146 | Event::KeyboardInput(_, n, _) => | |
| 147 | match n { | |
| 148 | 9 => return, | |
| 149 | 24 => rt -= 0.1, | |
| 150 | 25 => py -= dx, | |
| 151 | 26 => rt += 0.1, | |
| 152 | 38 => px -= dx, | |
| 153 | 39 => py += dx, | |
| 154 | 40 => px += dx, | |
| 155 | 44 => pz -= dx, | |
| 156 | 45 => pz += dx, | |
| 157 | _ => {}, | |
| 158 | }, | |
| 159 | _ => {}, | |
| 137 | 160 | } |
| 138 | 161 | } |
| 139 | 162 | } |
| 1 | 1 | extern crate glium; |
| 2 | extern crate image; | |
| 2 | 3 | |
| 3 | 4 | use bencode::Bencode; |
| 5 | use glium::{VertexBuffer, IndexBuffer}; | |
| 6 | use glium::texture::Texture2d; | |
| 4 | 7 | |
| 5 | 8 | #[derive(Debug, Copy, Clone)] |
| 6 | 9 | pub struct V3D { |
| 7 | 10 | pub pos: [f32; 3], |
| 11 | pub nrm: [f32; 3], | |
| 8 | 12 | pub tex: [f32; 2], |
| 9 | 13 | } |
| 10 | 14 | |
| 11 |
implement_vertex!(V3D, pos, |
|
| 15 | implement_vertex!(V3D, pos, nrm, tex); | |
| 12 | 16 | |
| 13 | 17 | #[derive(Debug, Clone)] |
| 14 | 18 | pub struct Model { |
| 15 | pub points: Vec<V3D>, | |
| 16 | pub tris: Vec<u16>, | |
| 19 | pub points: Vec<V3D>, | |
| 20 | pub tris: Vec<u16>, | |
| 21 | pub texture: Option<Vec<u8>>, | |
| 17 | 22 | } |
| 18 | 23 | |
| 19 | 24 | impl Model { |
| 31 | 36 | |
| 32 | 37 | pub fn load(is: &[u8]) -> Result<Model, String> { |
| 33 | 38 | let bs = try!(Bencode::parse(is)); |
| 34 |
|
|
| 39 | let tex = match bs.get_field("tex") { | |
| 40 | Ok(t) => Some(try!(t.as_bytes())), | |
| 41 | Err(_) => None, | |
| 42 | }; | |
| 35 | 43 | Ok(Model { |
| 36 | 44 | points: try!(try!(bs.get_field("pts")).map(load_v3d)), |
| 37 | 45 | tris: try!(try!(bs.get_field("tris")).map(|v| v.as_u16())), |
| 46 | texture: tex, | |
| 38 | 47 | }) |
| 39 | 48 | } |
| 40 | 49 | |
| 41 | pub fn get_vbuf(&self, display: &glium::Display) -> glium::VertexBuffer<V3D> { | |
| 42 | glium::VertexBuffer::new(display, self.points.as_slice()).unwrap() | |
| 50 | pub fn get_vbuf(&self, display: &glium::Display) -> VertexBuffer<V3D> { | |
| 51 | VertexBuffer::new(display, self.points.as_slice()).unwrap() | |
| 43 | 52 | } |
| 44 | 53 | |
| 45 | pub fn get_ibuf(&self, display: &glium::Display) -> glium::IndexBuffer<u16> { | |
| 46 | glium::IndexBuffer::new( | |
| 54 | pub fn get_ibuf(&self, display: &glium::Display) -> IndexBuffer<u16> { | |
| 55 | IndexBuffer::new( | |
| 47 | 56 | display, |
| 48 | 57 | glium::index::PrimitiveType::TrianglesList, |
| 49 | 58 | &self.tris).unwrap() |
| 59 | } | |
| 60 | ||
| 61 | pub fn get_tex(&self, display: &glium::Display) -> Option<Texture2d> { | |
| 62 | use std::io::Cursor; | |
| 63 | use glium::texture::RawImage2d; | |
| 64 | if let Some(ref tex) = self.texture { | |
| 65 | let img = image::load(Cursor::new(tex.clone()), | |
| 66 | image::PNG).unwrap().to_rgba(); | |
| 67 | let dims = img.dimensions(); | |
| 68 | let img = RawImage2d::from_raw_rgba_reversed(img.into_raw(), | |
| 69 | dims); | |
| 70 | Some(Texture2d::new(display, img).unwrap()) | |
| 71 | } else { | |
| 72 | None | |
| 73 | } | |
| 50 | 74 | } |
| 51 | 75 | } |
| 52 | 76 | |
| 53 | 77 | fn load_v3d(bs: &Bencode) -> Result<V3D, String> { |
| 54 | 78 | Ok(V3D { |
| 55 |
pos: [ try!(try!(bs.get_idx( |
|
| 79 | pos: [ try!(try!(bs.get_idx(0)).as_float()) * 0.5, | |
| 80 | try!(try!(bs.get_idx(1)).as_float()) * 0.5, | |
| 56 | 81 | try!(try!(bs.get_idx(2)).as_float()) * 0.5, |
| 57 |
|
|
| 82 | ], | |
| 83 | nrm: [ try!(try!(bs.get_idx(5)).as_float()), | |
| 84 | try!(try!(bs.get_idx(6)).as_float()), | |
| 85 | try!(try!(bs.get_idx(7)).as_float()), | |
| 58 | 86 | ], |
| 59 | 87 | tex: [ try!(try!(bs.get_idx(3)).as_float()), |
| 60 | 88 | try!(try!(bs.get_idx(4)).as_float()), |