Implement custom block conversion function

This commit is contained in:
NGnius 2021-10-18 18:00:07 -04:00
parent 6cc069a1f1
commit ff74437b6c
2 changed files with 27 additions and 10 deletions

View file

@ -5,4 +5,4 @@
#[cfg(feature = "robocraft")] #[cfg(feature = "robocraft")]
mod robocraft_3d; mod robocraft_3d;
#[cfg(feature = "robocraft")] #[cfg(feature = "robocraft")]
pub use robocraft_3d::cubes_to_model; pub use robocraft_3d::{cubes_to_model, cubes_to_model_with_lut};

View file

@ -1,27 +1,37 @@
use genmesh::{generators::Cube, Quad, MapToVertices, Vertices}; use genmesh::{generators::Cube, Quad, MapToVertices, Vertices, Vertex};
use obj; use obj;
use crate::robocraft; use crate::robocraft;
const SCALE: f32 = 0.5;
/// Convert a Robocraft robot to a 3D model in Wavefront OBJ format. /// Convert a Robocraft robot to a 3D model in Wavefront OBJ format.
pub fn cubes_to_model(robot: robocraft::Cubes) -> obj::Obj { pub fn cubes_to_model(robot: robocraft::Cubes) -> obj::Obj {
let mut positions = Vec::<[f32; 3]>::new(); cubes_to_model_with_lut(robot, default_model_lut)
let mut normals = Vec::<[f32; 3]>::new(); }
let mut objects = Vec::<obj::Object>::new();
/// Convert a Robocraft robot to a 3D model in Wavefront OBJ format using the provided lookup table function.
pub fn cubes_to_model_with_lut<F: FnMut(u32) -> Vec<Quad<Vertex>>>(robot: robocraft::Cubes, mut lut: F) -> obj::Obj {
let mut positions = Vec::<[f32; 3]>::new(); // vertex positions
let mut normals = Vec::<[f32; 3]>::new(); // vertex normals
let mut objects = Vec::<obj::Object>::new(); // blocks
let mut last = 0; let mut last = 0;
for cube in robot.into_iter() { for cube in robot.into_iter() {
// generate simple cube for every block
// TODO rotate blocks
let vertices = lut(cube.id); // Use lookup table to find correct id <-> block translation
positions.extend::<Vec::<[f32; 3]>>( positions.extend::<Vec::<[f32; 3]>>(
Cube::new().vertex(|v| vertices.clone().into_iter().vertex(|v|
[(v.pos.x * 0.5) + (cube.x as f32), (v.pos.y * 0.5) + (cube.y as f32), (v.pos.z * 0.5) + (cube.z as f32)]) [(v.pos.x * SCALE) + (cube.x as f32), (v.pos.y * SCALE) + (cube.y as f32), (v.pos.z * SCALE) + (cube.z as f32)])
.vertices() .vertices()
.collect() .collect()
); );
normals.extend::<Vec::<[f32; 3]>>( normals.extend::<Vec::<[f32; 3]>>(
Cube::new().vertex(|v| vertices.clone().into_iter().vertex(|v|
[(v.normal.x * 0.5) + (cube.x as f32), (v.normal.y * 0.5) + (cube.y as f32), (v.normal.z * 0.5) + (cube.z as f32)]) [(v.normal.x * SCALE) + (cube.x as f32), (v.normal.y * SCALE) + (cube.y as f32), (v.normal.z * SCALE) + (cube.z as f32)])
.vertices() .vertices()
.collect() .collect()
); );
let polys = Cube::new().vertex(|_| {last+=1; return last-1;}) let polys = vertices.clone().into_iter().vertex(|_| {last+=1; return last-1;})
.map(|Quad{x: v0, y: v1, z: v2, w: v3}| .map(|Quad{x: v0, y: v1, z: v2, w: v3}|
obj::SimplePolygon(vec![ obj::SimplePolygon(vec![
obj::IndexTuple(v0, Some(0), Some(v0)), obj::IndexTuple(v0, Some(0), Some(v0)),
@ -63,3 +73,10 @@ pub fn cubes_to_model(robot: robocraft::Cubes) -> obj::Obj {
path: std::path::PathBuf::new(), path: std::path::PathBuf::new(),
} }
} }
pub fn default_model_lut(id: u32) -> Vec<Quad<Vertex>> {
// TODO generate non-cube blocks properly
match id {
_ => Cube::new().collect(),
}
}