| 1 |  | 
                  extern crate glium;
                  
                 | 
              
| 2 |  | 
                  extern crate image;
                  
                 | 
              
| 3 |  | 
                  
                  
                 | 
              
| 4 |  | 
                  use glium::{VertexBuffer, IndexBuffer};
                  
                 | 
              
| 5 |  | 
                  use glium::texture::Texture2d;
                  
                 | 
              
| 6 |  | 
                  use std::vec;
                  
                 | 
              
| 7 |  | 
                  
                  
                 | 
              
| 8 |  | 
                  #[derive(Debug, Copy, Clone)]
                  
                 | 
              
| 9 |  | 
                  pub struct V3D {
                  
                 | 
              
| 10 |  | 
                      pub pos: [f32; 3],
                  
                 | 
              
| 11 |  | 
                      pub nrm: [f32; 3],
                  
                 | 
              
| 12 |  | 
                      pub tex: [f32; 2],
                  
                 | 
              
| 13 |  | 
                  }
                  
                 | 
              
| 14 |  | 
                  
                  
                 | 
              
| 15 |  | 
                  implement_vertex!(V3D, pos, nrm, tex);
                  
                 | 
              
| 16 |  | 
                  
                  
                 | 
              
| 17 |  | 
                  #[derive(Debug, Clone)]
                  
                 | 
              
| 18 |  | 
                  pub struct Model {
                  
                 | 
              
| 19 |  | 
                      pub points:  Vec<V3D>,
                  
                 | 
              
| 20 |  | 
                      pub tris:    Vec<u16>,
                  
                 | 
              
| 21 |  | 
                      pub texture: Option<Vec<u8>>,
                  
                 | 
              
| 22 |  | 
                  }
                  
                 | 
              
| 23 |  | 
                  
                  
                 | 
              
| 24 |  | 
                  impl Model {
                  
                 | 
              
| 25 |  | 
                      pub fn load_from_file(path: &str) -> Result<Model, String> {
                  
                 | 
              
| 26 |  | 
                          use std::fs::File;
                  
                 | 
              
| 27 |  | 
                          use std::io::Read;
                  
                 | 
              
| 28 |  | 
                          let mut f = match File::open(path) {
                  
                 | 
              
| 29 |  | 
                              Ok(f) => f,
                  
                 | 
              
| 30 |  | 
                              Err(_) => return Err("Unable to open file".to_string()),
                  
                 | 
              
| 31 |  | 
                          };
                  
                 | 
              
| 32 |  | 
                          let mut buf = Vec::new();
                  
                 | 
              
| 33 |  | 
                          let _ = f.read_to_end(&mut buf);
                  
                 | 
              
| 34 |  | 
                          (Reader { bytes: buf.into_iter() }).read_model()
                  
                 | 
              
| 35 |  | 
                      }
                  
                 | 
              
| 36 |  | 
                  
                  
                 | 
              
| 37 |  | 
                      pub fn get_vbuf(&self, display: &glium::Display) -> VertexBuffer<V3D> {
                  
                 | 
              
| 38 |  | 
                          VertexBuffer::new(display, self.points.as_slice()).unwrap()
                  
                 | 
              
| 39 |  | 
                      }
                  
                 | 
              
| 40 |  | 
                  
                  
                 | 
              
| 41 |  | 
                      pub fn get_ibuf(&self, display: &glium::Display) -> IndexBuffer<u16> {
                  
                 | 
              
| 42 |  | 
                          IndexBuffer::new(
                  
                 | 
              
| 43 |  | 
                              display,
                  
                 | 
              
| 44 |  | 
                              glium::index::PrimitiveType::TrianglesList,
                  
                 | 
              
| 45 |  | 
                              &self.tris).unwrap()
                  
                 | 
              
| 46 |  | 
                      }
                  
                 | 
              
| 47 |  | 
                  
                  
                 | 
              
| 48 |  | 
                      pub fn get_tex(&self, display: &glium::Display) -> Option<Texture2d> {
                  
                 | 
              
| 49 |  | 
                          use std::io::Cursor;
                  
                 | 
              
| 50 |  | 
                          use glium::texture::RawImage2d;
                  
                 | 
              
| 51 |  | 
                          if let Some(ref tex) = self.texture {
                  
                 | 
              
| 52 |  | 
                              let img = image::load(Cursor::new(tex.clone()),
                  
                 | 
              
| 53 |  | 
                                                    image::PNG).unwrap().to_rgba();
                  
                 | 
              
| 54 |  | 
                              let dims = img.dimensions();
                  
                 | 
              
| 55 |  | 
                              let img = RawImage2d::from_raw_rgba_reversed(img.into_raw(),
                  
                 | 
              
| 56 |  | 
                                                                           dims);
                  
                 | 
              
| 57 |  | 
                              Some(Texture2d::new(display, img).unwrap())
                  
                 | 
              
| 58 |  | 
                          } else {
                  
                 | 
              
| 59 |  | 
                              None
                  
                 | 
              
| 60 |  | 
                          }
                  
                 | 
              
| 61 |  | 
                      }
                  
                 | 
              
| 62 |  | 
                  }
                  
                 | 
              
| 63 |  | 
                  
                  
                 | 
              
| 64 |  | 
                  /// A `Reader` is just a tiny wrapper over a mutable byte iterator, so we
                  
                 | 
              
| 65 |  | 
                  /// can parse things more easily.
                  
                 | 
              
| 66 |  | 
                  struct Reader {
                  
                 | 
              
| 67 |  | 
                      pub bytes: vec::IntoIter<u8>,
                  
                 | 
              
| 68 |  | 
                  }
                  
                 | 
              
| 69 |  | 
                  
                  
                 | 
              
| 70 |  | 
                  #[test]
                  
                 | 
              
| 71 |  | 
                  fn reader_tests() {
                  
                 | 
              
| 72 |  | 
                      assert!(Reader::from_slice(&[0x00]).read_twip() == Ok(-32.0));
                  
                 | 
              
| 73 |  | 
                      assert!(Reader::from_slice(&[0x00]).read_prefix_int() == Ok(0x00));
                  
                 | 
              
| 74 |  | 
                      assert!(Reader::from_slice(&[0x7f]).read_prefix_int() == Ok(0x7f));
                  
                 | 
              
| 75 |  | 
                      assert!(Reader::from_slice(&[0x80,0xff]).read_prefix_int() == Ok(0xff));
                  
                 | 
              
| 76 |  | 
                  }
                  
                 | 
              
| 77 |  | 
                  
                  
                 | 
              
| 78 |  | 
                  impl Reader {
                  
                 | 
              
| 79 |  | 
                      fn from_slice(lst: &[u8]) -> Self {
                  
                 | 
              
| 80 |  | 
                          Reader { bytes: lst.to_vec().into_iter() }
                  
                 | 
              
| 81 |  | 
                      }
                  
                 | 
              
| 82 |  | 
                      /// This gets the next byte, or fails if it's out of input.
                  
                 | 
              
| 83 |  | 
                      fn next(&mut self) -> Result<u8, String> {
                  
                 | 
              
| 84 |  | 
                          Ok(try!(self.bytes.next().ok_or("out of input")))
                  
                 | 
              
| 85 |  | 
                      }
                  
                 | 
              
| 86 |  | 
                  
                  
                 | 
              
| 87 |  | 
                      /// This reads a one-byte or two-byte float in the rough range of
                  
                 | 
              
| 88 |  | 
                      /// (192 .. -128). We're going to treat all models as if they're
                  
                 | 
              
| 89 |  | 
                      /// supposed to be centered in a 64x64x64 square, so this gives
                  
                 | 
              
| 90 |  | 
                      /// us 128 units on either side of the central square, as well.
                  
                 | 
              
| 91 |  | 
                      fn read_twip(&mut self) -> Result<f32, String> {
                  
                 | 
              
| 92 |  | 
                          let b1 = try!(self.next());
                  
                 | 
              
| 93 |  | 
                          if (b1 & 0x80) != 0 {
                  
                 | 
              
| 94 |  | 
                              let b2 = try!(self.next());
                  
                 | 
              
| 95 |  | 
                              let val = ((b1 as u16 & 0x7f) << 8) | b2 as u16;
                  
                 | 
              
| 96 |  | 
                              Ok((val as f32 / 102.0) - 128.0)
                  
                 | 
              
| 97 |  | 
                          } else {
                  
                 | 
              
| 98 |  | 
                              Ok((b1 as f32) - 32.0)
                  
                 | 
              
| 99 |  | 
                          }
                  
                 | 
              
| 100 |  | 
                      }
                  
                 | 
              
| 101 |  | 
                  
                  
                 | 
              
| 102 |  | 
                      /// This reads a single byte and treats it as a ratio.
                  
                 | 
              
| 103 |  | 
                      fn read_ratio(&mut self) -> Result<f32, String> {
                  
                 | 
              
| 104 |  | 
                          let b = try!(self.next());
                  
                 | 
              
| 105 |  | 
                          Ok(b as f32 / 255.0)
                  
                 | 
              
| 106 |  | 
                      }
                  
                 | 
              
| 107 |  | 
                  
                  
                 | 
              
| 108 |  | 
                      /// This reads a 64-bit int with a packed PrefixInteger representation.
                  
                 | 
              
| 109 |  | 
                      /// The shorter the int, the shorter the representation.
                  
                 | 
              
| 110 |  | 
                      fn read_prefix_int(&mut self) -> Result<u64, String> {
                  
                 | 
              
| 111 |  | 
                          fn match_bits(n: u8, mask: u8) -> bool {
                  
                 | 
              
| 112 |  | 
                              n & mask == mask
                  
                 | 
              
| 113 |  | 
                          }
                  
                 | 
              
| 114 |  | 
                          let b = try!(self.next());
                  
                 | 
              
| 115 |  | 
                          if match_bits(b, 0xff)      { self.continue_prefix_int(8, 0) }
                  
                 | 
              
| 116 |  | 
                          else if match_bits(b, 0xfe) { self.continue_prefix_int(7, 0) }
                  
                 | 
              
| 117 |  | 
                          else if match_bits(b, 0xfc) { self.continue_prefix_int(6, b & 0x01) }
                  
                 | 
              
| 118 |  | 
                          else if match_bits(b, 0xf8) { self.continue_prefix_int(5, b & 0x03) }
                  
                 | 
              
| 119 |  | 
                          else if match_bits(b, 0xf0) { self.continue_prefix_int(4, b & 0x07) }
                  
                 | 
              
| 120 |  | 
                          else if match_bits(b, 0xe0) { self.continue_prefix_int(3, b & 0x0f) }
                  
                 | 
              
| 121 |  | 
                          else if match_bits(b, 0xc0) { self.continue_prefix_int(2, b & 0x1f) }
                  
                 | 
              
| 122 |  | 
                          else if match_bits(b, 0x80) { self.continue_prefix_int(1, b & 0x3f) }
                  
                 | 
              
| 123 |  | 
                          else {                        self.continue_prefix_int(0, b) }
                  
                 | 
              
| 124 |  | 
                      }
                  
                 | 
              
| 125 |  | 
                  
                  
                 | 
              
| 126 |  | 
                      /// This is a helper function for parsing prefix ints, too.
                  
                 | 
              
| 127 |  | 
                      fn continue_prefix_int(&mut self, mut left: u8, upper: u8) -> Result<u64, String> {
                  
                 | 
              
| 128 |  | 
                          let mut ret = upper as u64;
                  
                 | 
              
| 129 |  | 
                          while left > 0 {
                  
                 | 
              
| 130 |  | 
                              left -= 1;
                  
                 | 
              
| 131 |  | 
                              ret = (ret << 8) | try!(self.next()) as u64;
                  
                 | 
              
| 132 |  | 
                          }
                  
                 | 
              
| 133 |  | 
                          Ok(ret)
                  
                 | 
              
| 134 |  | 
                      }
                  
                 | 
              
| 135 |  | 
                  
                  
                 | 
              
| 136 |  | 
                      /// This reads a single V3D: three twips for the x/y/z, three twips
                  
                 | 
              
| 137 |  | 
                      /// for the normal, and two ratios for the uv coords.
                  
                 | 
              
| 138 |  | 
                      fn read_v3d(&mut self) -> Result<V3D, String> {
                  
                 | 
              
| 139 |  | 
                          Ok(V3D { pos: [ try!(self.read_twip()) * 0.1,
                  
                 | 
              
| 140 |  | 
                                          try!(self.read_twip()) * 0.1,
                  
                 | 
              
| 141 |  | 
                                          try!(self.read_twip()) * 0.1],
                  
                 | 
              
| 142 |  | 
                                   nrm: [ try!(self.read_twip()),
                  
                 | 
              
| 143 |  | 
                                          try!(self.read_twip()),
                  
                 | 
              
| 144 |  | 
                                          try!(self.read_twip()) ],
                  
                 | 
              
| 145 |  | 
                                   tex: [ try!(self.read_ratio()),
                  
                 | 
              
| 146 |  | 
                                          try!(self.read_ratio()) ],
                  
                 | 
              
| 147 |  | 
                          })
                  
                 | 
              
| 148 |  | 
                      }
                  
                 | 
              
| 149 |  | 
                  
                  
                 | 
              
| 150 |  | 
                      /// This reads a PrefixInteger to find out how many other things to read,
                  
                 | 
              
| 151 |  | 
                      /// and then reads that number of things.
                  
                 | 
              
| 152 |  | 
                      fn read_several<F, R>(&mut self, reader: F) -> Result<Vec<R>, String>
                  
                 | 
              
| 153 |  | 
                          where F: Fn(&mut Reader) -> Result<R, String>
                  
                 | 
              
| 154 |  | 
                      {
                  
                 | 
              
| 155 |  | 
                          let ct = try!(self.read_prefix_int());
                  
                 | 
              
| 156 |  | 
                          let mut ret = Vec::with_capacity(ct as usize);
                  
                 | 
              
| 157 |  | 
                          for _ in 0..ct {
                  
                 | 
              
| 158 |  | 
                              ret.push(try!(reader(self)))
                  
                 | 
              
| 159 |  | 
                          }
                  
                 | 
              
| 160 |  | 
                          Ok(ret)
                  
                 | 
              
| 161 |  | 
                      }
                  
                 | 
              
| 162 |  | 
                  
                  
                 | 
              
| 163 |  | 
                      /// This reads a model: right now, a list of tris, followed by a list of
                  
                 | 
              
| 164 |  | 
                      /// v3ds. This could be very small: a V3D could be as small as eight bytes,
                  
                 | 
              
| 165 |  | 
                      /// an index as small as one, and each size tag can be one byte. A simple
                  
                 | 
              
| 166 |  | 
                      /// model that contains only a triangle is going to be
                  
                 | 
              
| 167 |  | 
                      ///   (1 + 3*8) + (1 + 3) == 28 bytes
                  
                 | 
              
| 168 |  | 
                      /// in contrast to the older UTM models, where an equivalent would be 50
                  
                 | 
              
| 169 |  | 
                      /// bytes per V3D and a two-byte overhead per list, as well as miscellaneous
                  
                 | 
              
| 170 |  | 
                      /// structure data, so
                  
                 | 
              
| 171 |  | 
                      ///   (2 + 3*50) + (2 + 3 * 3) + 13 == 176 bytes
                  
                 | 
              
| 172 |  | 
                      /// That's a pretty good savings!
                  
                 | 
              
| 173 |  | 
                      fn read_model(&mut self) -> Result<Model, String> {
                  
                 | 
              
| 174 |  | 
                          Ok(Model {
                  
                 | 
              
| 175 |  | 
                              tris: try!(self.read_several(|r| r.read_prefix_int().map(|x| x as u16))),
                  
                 | 
              
| 176 |  | 
                              points: try!(self.read_several(|r| r.read_v3d())),
                  
                 | 
              
| 177 |  | 
                              texture: None,
                  
                 | 
              
| 178 |  | 
                          })
                  
                 | 
              
| 179 |  | 
                      }
                  
                 | 
              
| 180 |  | 
                  }
                  
                 |