model.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. extern crate glium;
  2. extern crate image;
  3. use glium::{VertexBuffer, IndexBuffer};
  4. use glium::texture::Texture2d;
  5. use therm_util::reader::ByteReader;
  6. #[derive(Debug, Copy, Clone)]
  7. pub struct V3D {
  8. pub pos: [f32; 3],
  9. pub nrm: [f32; 3],
  10. pub tex: [f32; 2],
  11. }
  12. implement_vertex!(V3D, pos, nrm, tex);
  13. impl V3D {
  14. pub fn from_reader<Rd>(reader: &mut ByteReader<Rd>) -> Result<V3D, String>
  15. where Rd: Iterator<Item=u8>
  16. {
  17. Ok(V3D { pos: [ try!(reader.read_twip()) * 0.1,
  18. try!(reader.read_twip()) * 0.1,
  19. try!(reader.read_twip()) * 0.1],
  20. nrm: [ try!(reader.read_twip()),
  21. try!(reader.read_twip()),
  22. try!(reader.read_twip()) ],
  23. tex: [ try!(reader.read_ratio()),
  24. try!(reader.read_ratio()) ],
  25. })
  26. }
  27. }
  28. #[derive(Debug, Clone)]
  29. pub struct Model {
  30. pub points: Vec<V3D>,
  31. pub tris: Vec<u16>,
  32. pub texture: Option<Vec<u8>>,
  33. }
  34. impl Model {
  35. pub fn load_from_file(path: &str) -> Result<Model, String> {
  36. let mut reader = ByteReader::from_file(path).unwrap();
  37. Model::from_reader(&mut reader)
  38. }
  39. pub fn from_reader<T>(reader: &mut ByteReader<T>) -> Result<Model, String>
  40. where T: Iterator<Item=u8>
  41. {
  42. Ok(Model {
  43. tris: try!(reader.read_several(|r| r.read_prefix_int().map(|x| x as u16))),
  44. points: try!(reader.read_several(V3D::from_reader)),
  45. texture: None,
  46. })
  47. }
  48. pub fn get_vbuf(&self, display: &glium::Display) -> VertexBuffer<V3D> {
  49. VertexBuffer::new(display, self.points.as_slice()).unwrap()
  50. }
  51. pub fn get_ibuf(&self, display: &glium::Display) -> IndexBuffer<u16> {
  52. IndexBuffer::new(
  53. display,
  54. glium::index::PrimitiveType::TrianglesList,
  55. &self.tris).unwrap()
  56. }
  57. pub fn get_tex(&self, display: &glium::Display) -> Option<Texture2d> {
  58. use std::io::Cursor;
  59. use glium::texture::RawImage2d;
  60. if let Some(ref tex) = self.texture {
  61. let img = image::load(Cursor::new(tex.clone()),
  62. image::PNG).unwrap().to_rgba();
  63. let dims = img.dimensions();
  64. let img = RawImage2d::from_raw_rgba_reversed(img.into_raw(),
  65. dims);
  66. Some(Texture2d::new(display, img).unwrap())
  67. } else {
  68. None
  69. }
  70. }
  71. }