Implement basic 3D model conversion functionality for Robocraft bots
This commit is contained in:
parent
705fae29b3
commit
0d6ea85bcd
6 changed files with 99 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
/.idea
|
/.idea
|
||||||
/parsable_macro_derive/target
|
/parsable_macro_derive/target
|
||||||
|
/tests/test-*.obj
|
||||||
|
|
|
@ -23,6 +23,8 @@ chrono = {version = "^0.4", optional = true}
|
||||||
fasthash = {version = "^0.4", optional = true}
|
fasthash = {version = "^0.4", optional = true}
|
||||||
libfj_parsable_macro_derive = {version = "0.5.3", optional = true}
|
libfj_parsable_macro_derive = {version = "0.5.3", optional = true}
|
||||||
#libfj_parsable_macro_derive = {path = "./parsable_macro_derive", optional = true}
|
#libfj_parsable_macro_derive = {path = "./parsable_macro_derive", optional = true}
|
||||||
|
obj = {version = "^0.10", optional = true}
|
||||||
|
genmesh = {version = "^0.6", optional = true}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.4.0", features = ["macros"]}
|
tokio = { version = "1.4.0", features = ["macros"]}
|
||||||
|
@ -32,3 +34,4 @@ simple = ["ureq"]
|
||||||
robocraft = ["reqwest"]
|
robocraft = ["reqwest"]
|
||||||
cardlife = ["reqwest"]
|
cardlife = ["reqwest"]
|
||||||
techblox = ["chrono", "fasthash", "libfj_parsable_macro_derive"]
|
techblox = ["chrono", "fasthash", "libfj_parsable_macro_derive"]
|
||||||
|
convert = ["obj", "genmesh"]
|
||||||
|
|
8
src/convert/mod.rs
Normal file
8
src/convert/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
//! Conversion utility functions.
|
||||||
|
//!
|
||||||
|
//! This will contain ways to convert data from one game to another as well as into standard formats.
|
||||||
|
|
||||||
|
#[cfg(feature = "robocraft")]
|
||||||
|
mod robocraft_3d;
|
||||||
|
#[cfg(feature = "robocraft")]
|
||||||
|
pub use robocraft_3d::cubes_to_model;
|
65
src/convert/robocraft_3d.rs
Normal file
65
src/convert/robocraft_3d.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use genmesh::{generators::Cube, Quad, MapToVertices, Vertices};
|
||||||
|
use obj;
|
||||||
|
use crate::robocraft;
|
||||||
|
|
||||||
|
/// Convert a Robocraft robot to a 3D model in Wavefront OBJ format.
|
||||||
|
pub fn cubes_to_model(robot: robocraft::Cubes) -> obj::Obj {
|
||||||
|
let mut positions = Vec::<[f32; 3]>::new();
|
||||||
|
let mut normals = Vec::<[f32; 3]>::new();
|
||||||
|
let mut objects = Vec::<obj::Object>::new();
|
||||||
|
let mut last = 0;
|
||||||
|
for cube in robot.into_iter() {
|
||||||
|
positions.extend::<Vec::<[f32; 3]>>(
|
||||||
|
Cube::new().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)])
|
||||||
|
.vertices()
|
||||||
|
.collect()
|
||||||
|
);
|
||||||
|
normals.extend::<Vec::<[f32; 3]>>(
|
||||||
|
Cube::new().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)])
|
||||||
|
.vertices()
|
||||||
|
.collect()
|
||||||
|
);
|
||||||
|
let polys = Cube::new().vertex(|_| {last+=1; return last-1;})
|
||||||
|
.map(|Quad{x: v0, y: v1, z: v2, w: v3}|
|
||||||
|
obj::SimplePolygon(vec![
|
||||||
|
obj::IndexTuple(v0, Some(0), Some(v0)),
|
||||||
|
obj::IndexTuple(v1, Some(0), Some(v1)),
|
||||||
|
obj::IndexTuple(v2, Some(0), Some(v2)),
|
||||||
|
obj::IndexTuple(v3, Some(0), Some(v3))
|
||||||
|
])
|
||||||
|
/*obj::SimplePolygon(vec![
|
||||||
|
obj::IndexTuple(v0, None, None),
|
||||||
|
obj::IndexTuple(v1, None, None),
|
||||||
|
obj::IndexTuple(v2, None, None),
|
||||||
|
obj::IndexTuple(v3, None, None)
|
||||||
|
])*/
|
||||||
|
).collect();
|
||||||
|
objects.push(
|
||||||
|
obj::Object{
|
||||||
|
name: format!("Cube-ID{}-NUM{}", cube.id, objects.len()),
|
||||||
|
groups: vec![
|
||||||
|
obj::Group {
|
||||||
|
name: format!("Cube-ID{}-NUM{}-0", cube.id, objects.len()),
|
||||||
|
index: 0,
|
||||||
|
material: None,
|
||||||
|
polys: polys
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
println!("Last (index): {}, Vertices (len): {}", last, positions.len());
|
||||||
|
|
||||||
|
obj::Obj{
|
||||||
|
data: obj::ObjData {
|
||||||
|
position: positions,
|
||||||
|
texture: vec![[0.0, 0.0]],
|
||||||
|
normal: normals,
|
||||||
|
objects: objects,
|
||||||
|
material_libs: Vec::new(),
|
||||||
|
},
|
||||||
|
path: std::path::PathBuf::new(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,3 +11,5 @@ pub mod robocraft;
|
||||||
pub mod robocraft_simple;
|
pub mod robocraft_simple;
|
||||||
#[cfg(feature = "techblox")]
|
#[cfg(feature = "techblox")]
|
||||||
pub mod techblox;
|
pub mod techblox;
|
||||||
|
#[cfg(feature = "convert")]
|
||||||
|
pub mod convert;
|
||||||
|
|
20
tests/convert_3d.rs
Normal file
20
tests/convert_3d.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#[cfg(all(feature = "robocraft", feature = "convert"))]
|
||||||
|
use libfj::convert::cubes_to_model;
|
||||||
|
#[cfg(all(feature = "robocraft", feature = "convert"))]
|
||||||
|
use libfj::robocraft;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "robocraft", feature = "convert"))]
|
||||||
|
#[tokio::test]
|
||||||
|
async fn convert_to_obj() -> Result<(), ()> {
|
||||||
|
let api = robocraft::FactoryAPI::new();
|
||||||
|
let result = api.list().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let robot = api.get(result.unwrap().response.roboshop_items[0].item_id).await;
|
||||||
|
assert!(robot.is_ok());
|
||||||
|
let cubes = robot.unwrap();
|
||||||
|
let obj = cubes_to_model(robocraft::Cubes::from(cubes.clone()));
|
||||||
|
let save_result = obj.save(format!("tests/test-{}.obj", cubes.response.item_id));
|
||||||
|
//save_result.unwrap();
|
||||||
|
assert!(save_result.is_ok());
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue