An unofficial collection of APIs used in FreeJam games and mods
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.1KB

  1. use genmesh::{generators::Cube, Quad, MapToVertices, Vertices, Vertex};
  2. use obj;
  3. use crate::robocraft;
  4. const SCALE: f32 = 0.5;
  5. /// Convert a Robocraft robot to a 3D model in Wavefront OBJ format.
  6. pub fn cubes_to_model(robot: robocraft::Cubes) -> obj::Obj {
  7. cubes_to_model_with_lut(robot, default_model_lut)
  8. }
  9. /// Convert a Robocraft robot to a 3D model in Wavefront OBJ format using the provided lookup table function.
  10. pub fn cubes_to_model_with_lut<F: FnMut(u32) -> Vec<Quad<Vertex>>>(robot: robocraft::Cubes, mut lut: F) -> obj::Obj {
  11. let mut positions = Vec::<[f32; 3]>::new(); // vertex positions
  12. let mut normals = Vec::<[f32; 3]>::new(); // vertex normals
  13. let mut objects = Vec::<obj::Object>::new(); // blocks
  14. let mut last = 0;
  15. for cube in robot.into_iter() {
  16. // generate simple cube for every block
  17. // TODO rotate blocks
  18. let vertices = lut(cube.id); // Use lookup table to find correct id <-> block translation
  19. positions.extend::<Vec::<[f32; 3]>>(
  20. vertices.clone().into_iter().vertex(|v|
  21. [(v.pos.x * SCALE) + (cube.x as f32), (v.pos.y * SCALE) + (cube.y as f32), (v.pos.z * SCALE) + (cube.z as f32)])
  22. .vertices()
  23. .collect()
  24. );
  25. normals.extend::<Vec::<[f32; 3]>>(
  26. vertices.clone().into_iter().vertex(|v|
  27. [(v.normal.x * SCALE) + (cube.x as f32), (v.normal.y * SCALE) + (cube.y as f32), (v.normal.z * SCALE) + (cube.z as f32)])
  28. .vertices()
  29. .collect()
  30. );
  31. let polys = vertices.clone().into_iter().vertex(|_| {last+=1; return last-1;})
  32. .map(|Quad{x: v0, y: v1, z: v2, w: v3}|
  33. obj::SimplePolygon(vec![
  34. obj::IndexTuple(v0, Some(0), Some(v0)),
  35. obj::IndexTuple(v1, Some(0), Some(v1)),
  36. obj::IndexTuple(v2, Some(0), Some(v2)),
  37. obj::IndexTuple(v3, Some(0), Some(v3))
  38. ])
  39. /*obj::SimplePolygon(vec![
  40. obj::IndexTuple(v0, None, None),
  41. obj::IndexTuple(v1, None, None),
  42. obj::IndexTuple(v2, None, None),
  43. obj::IndexTuple(v3, None, None)
  44. ])*/
  45. ).collect();
  46. objects.push(
  47. obj::Object{
  48. name: format!("Cube-ID{}-NUM{}", cube.id, objects.len()),
  49. groups: vec![
  50. obj::Group {
  51. name: format!("Cube-ID{}-NUM{}-0", cube.id, objects.len()),
  52. index: 0,
  53. material: None,
  54. polys: polys
  55. },
  56. ]
  57. }
  58. );
  59. }
  60. println!("Last (index): {}, Vertices (len): {}", last, positions.len());
  61. obj::Obj{
  62. data: obj::ObjData {
  63. position: positions,
  64. texture: vec![[0.0, 0.0]],
  65. normal: normals,
  66. objects: objects,
  67. material_libs: Vec::new(),
  68. },
  69. path: std::path::PathBuf::new(),
  70. }
  71. }
  72. pub fn default_model_lut(id: u32) -> Vec<Quad<Vertex>> {
  73. // TODO generate non-cube blocks properly
  74. match id {
  75. _ => Cube::new().collect(),
  76. }
  77. }