Created
September 20, 2020 19:33
-
-
Save superdump/202d9db357a4fae8e845deb98ebaf14c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// shapes.rs | |
use bevy::{ | |
prelude::*, | |
render::{ | |
mesh::{Mesh, VertexAttribute}, | |
pipeline::PrimitiveTopology, | |
}, | |
}; | |
pub struct Cone { | |
pub radius: f32, | |
pub segments: usize, | |
pub height: f32, | |
} | |
impl Default for Cone { | |
fn default() -> Self { | |
Cone { | |
radius: 0.5f32, | |
segments: 32, | |
height: 1.0f32, | |
} | |
} | |
} | |
impl From<Cone> for Mesh { | |
fn from(cone: Cone) -> Self { | |
let mut positions = Vec::with_capacity(cone.segments + 2); | |
let mut normals = Vec::with_capacity(cone.segments + 2); | |
let mut uvs = Vec::with_capacity(cone.segments + 2); | |
let mut indices = Vec::with_capacity(cone.segments + 2); | |
// bottom | |
positions.push([0.0, 0.0, 0.0]); | |
normals.push([0.0, -1.0, 0.0]); | |
uvs.push([0.5, 0.0]); | |
let angle = 2.0f32 * std::f32::consts::PI / cone.segments as f32; | |
// circular base of cone | |
let frac_h_2 = Vec3::new(0.0f32, 0.5f32 * cone.height, 0.0f32); | |
for i in 0..cone.segments { | |
let (z, x) = (angle * i as f32).sin_cos(); | |
let (z, x) = (cone.radius * z, cone.radius * x); | |
let position = Vec3::new(x, 0.0f32, z); | |
positions.push(*position.as_ref()); | |
let normal = (position - frac_h_2).normalize(); | |
normals.push(*normal.as_ref()); | |
// FIXME | |
uvs.push([0.5, 0.0]); | |
} | |
// top | |
positions.push([0.0, cone.height, 0.0]); | |
normals.push([0.0, 1.0, 0.0]); | |
uvs.push([0.5, 1.0]); | |
for i in 0..cone.segments { | |
// bottom circle | |
indices.append(&mut vec![ | |
0u32, | |
(1 + (i % cone.segments)) as u32, | |
(1 + ((i + 1) % cone.segments)) as u32, | |
]); | |
// cone | |
indices.append(&mut vec![ | |
(cone.segments + 1) as u32, | |
(1 + ((i + 1) % cone.segments)) as u32, | |
(1 + (i % cone.segments)) as u32, | |
]); | |
} | |
Mesh { | |
primitive_topology: PrimitiveTopology::TriangleList, | |
attributes: vec![ | |
VertexAttribute::position(positions), | |
VertexAttribute::normal(normals), | |
VertexAttribute::uv(uvs), | |
], | |
indices: Some(indices), | |
} | |
} | |
} | |
pub struct Cylinder { | |
pub radius: f32, | |
pub segments: usize, | |
pub height: f32, | |
} | |
impl Default for Cylinder { | |
fn default() -> Self { | |
Cylinder { | |
radius: 0.5f32, | |
segments: 32, | |
height: 1.0f32, | |
} | |
} | |
} | |
impl From<Cylinder> for Mesh { | |
fn from(cylinder: Cylinder) -> Self { | |
let mut positions = Vec::with_capacity(cylinder.segments + 2); | |
let mut normals = Vec::with_capacity(cylinder.segments + 2); | |
let mut uvs = Vec::with_capacity(cylinder.segments + 2); | |
let mut indices = Vec::with_capacity(cylinder.segments + 2); | |
// bottom | |
positions.push([0.0, 0.0, 0.0]); | |
normals.push([0.0, -1.0, 0.0]); | |
uvs.push([0.5, 0.0]); | |
// top | |
positions.push([0.0, cylinder.height, 0.0]); | |
normals.push([0.0, 1.0, 0.0]); | |
uvs.push([0.5, 1.0]); | |
let angle = 2.0f32 * std::f32::consts::PI / cylinder.segments as f32; | |
// circular base of cylinder | |
for i in 0..cylinder.segments { | |
let (z, x) = (angle * i as f32).sin_cos(); | |
let (z, x) = (cylinder.radius * z, cylinder.radius * x); | |
let magnitude = (x * x + z * z).sqrt(); | |
positions.push([x, 0.0, z]); | |
normals.push([x / magnitude, 0.0, z / magnitude]); | |
// FIXME | |
uvs.push([0.5, 0.0]); | |
} | |
// circular top of cylinder | |
for i in 0..cylinder.segments { | |
let (z, x) = (angle * i as f32).sin_cos(); | |
let (z, x) = (cylinder.radius * z, cylinder.radius * x); | |
let magnitude = (x * x + z * z).sqrt(); | |
positions.push([x, cylinder.height, z]); | |
normals.push([x / magnitude, 0.0, z / magnitude]); | |
// FIXME | |
uvs.push([0.5, cylinder.height]); | |
} | |
for i in 0..cylinder.segments { | |
let bottom_offset = 2; | |
let top_offset = 2 + cylinder.segments; | |
// bottom circle | |
indices.append(&mut vec![ | |
0u32, | |
(bottom_offset + (i % cylinder.segments)) as u32, | |
(bottom_offset + ((i + 1) % cylinder.segments)) as u32, | |
]); | |
// cylinder | |
indices.append(&mut vec![ | |
(bottom_offset + ((i + 1) % cylinder.segments)) as u32, | |
(bottom_offset + (i % cylinder.segments)) as u32, | |
(top_offset + (i % cylinder.segments)) as u32, | |
]); | |
indices.append(&mut vec![ | |
(top_offset + (i % cylinder.segments)) as u32, | |
(top_offset + ((i + 1) % cylinder.segments)) as u32, | |
(bottom_offset + ((i + 1) % cylinder.segments)) as u32, | |
]); | |
// top circle | |
indices.append(&mut vec![ | |
1u32, | |
(top_offset + ((i + 1) % cylinder.segments)) as u32, | |
(top_offset + (i % cylinder.segments)) as u32, | |
]); | |
} | |
Mesh { | |
primitive_topology: PrimitiveTopology::TriangleList, | |
attributes: vec![ | |
VertexAttribute::position(positions), | |
VertexAttribute::normal(normals), | |
VertexAttribute::uv(uvs), | |
], | |
indices: Some(indices), | |
} | |
} | |
} | |
// debug.rs | |
use crate::{shapes::*, types::CameraTag}; | |
use bevy::{ | |
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin}, | |
prelude::*, | |
}; | |
#[derive(Default)] | |
struct Debug(bool); | |
pub struct DebugPlugin; | |
impl Plugin for DebugPlugin { | |
fn build(&self, app: &mut AppBuilder) { | |
app.init_resource::<Debug>() | |
.add_plugin(FrameTimeDiagnosticsPlugin::default()) | |
.add_startup_system(debug_setup.system()) | |
.add_system(axes_system.system()); | |
} | |
} | |
struct AxesTag; | |
fn axes_system( | |
mut camera_query: Query<(&CameraTag, &Transform)>, | |
mut axes_query: Query<(&AxesTag, &mut Transform)>, | |
) { | |
let mut cam_temp = camera_query.iter(); | |
let (_, camera_transform) = cam_temp.iter().next().unwrap(); | |
let mut axes_temp = axes_query.iter(); | |
let (_, mut axes_transform) = axes_temp.iter().next().unwrap(); | |
let forward = camera_transform.rotation() * Vec3::unit_z(); | |
let right = camera_transform.rotation() * Vec3::unit_x(); | |
let up = camera_transform.rotation() * Vec3::unit_y(); | |
let mut translation = camera_transform.translation(); | |
translation += -2.0f32 * forward + 1.25f32 * right - 0.68f32 * up; | |
axes_transform.set_translation(translation); | |
} | |
fn debug_setup( | |
mut commands: Commands, | |
asset_server: Res<AssetServer>, | |
mut meshes: ResMut<Assets<Mesh>>, | |
mut color_materials: ResMut<Assets<ColorMaterial>>, | |
mut standard_materials: ResMut<Assets<StandardMaterial>>, | |
) { | |
// In-scene | |
let cylinder_mesh = meshes.add(Mesh::from(Cylinder { | |
height: 0.85f32, | |
radius: 0.03f32, | |
..Default::default() | |
})); | |
let cone_mesh = meshes.add(Mesh::from(Cone { | |
height: 0.15f32, | |
radius: 0.07f32, | |
..Default::default() | |
})); | |
let red = standard_materials.add(Color::RED.into()); | |
let green = standard_materials.add(Color::GREEN.into()); | |
let blue = standard_materials.add(Color::BLUE.into()); | |
commands | |
.spawn(( | |
GlobalTransform::identity(), | |
Transform::from_scale(0.1f32), | |
AxesTag, | |
)) | |
.with_children(|axes_root| { | |
axes_root | |
.spawn(( | |
GlobalTransform::identity(), | |
Transform::from_rotation(Quat::from_rotation_z(-std::f32::consts::FRAC_PI_2)), | |
)) | |
.with_children(|axis_root| { | |
axis_root | |
.spawn(PbrComponents { | |
material: red, | |
mesh: cone_mesh, | |
transform: Transform::from_translation(Vec3::new( | |
0.0f32, 0.85f32, 0.0f32, | |
)), | |
..Default::default() | |
}) | |
.spawn(PbrComponents { | |
material: red, | |
mesh: cylinder_mesh, | |
..Default::default() | |
}); | |
}) | |
.spawn((GlobalTransform::identity(), Transform::identity())) | |
.with_children(|axis_root| { | |
axis_root | |
.spawn(PbrComponents { | |
material: green, | |
mesh: cone_mesh, | |
transform: Transform::from_translation(Vec3::new( | |
0.0f32, 0.85f32, 0.0f32, | |
)), | |
..Default::default() | |
}) | |
.spawn(PbrComponents { | |
material: green, | |
mesh: cylinder_mesh, | |
..Default::default() | |
}); | |
}) | |
.spawn(( | |
GlobalTransform::identity(), | |
Transform::from_rotation(Quat::from_rotation_x(std::f32::consts::FRAC_PI_2)), | |
)) | |
.with_children(|axis_root| { | |
axis_root | |
.spawn(PbrComponents { | |
material: blue, | |
mesh: cone_mesh, | |
transform: Transform::from_translation(Vec3::new( | |
0.0f32, 0.85f32, 0.0f32, | |
)), | |
..Default::default() | |
}) | |
.spawn(PbrComponents { | |
material: blue, | |
mesh: cylinder_mesh, | |
..Default::default() | |
}); | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment