Skip to content

Commit

Permalink
Cuboid -> Box, re-add cube, move shapes to their own file
Browse files Browse the repository at this point in the history
  • Loading branch information
cart committed Nov 21, 2020
1 parent d3f8bad commit b95c518
Show file tree
Hide file tree
Showing 13 changed files with 345 additions and 325 deletions.
306 changes: 0 additions & 306 deletions crates/bevy_render/src/mesh/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,312 +220,6 @@ impl Mesh {
}
}

/// Generation for some primitive shape meshes.
pub mod shape {
use super::{Indices, Mesh};
use crate::pipeline::PrimitiveTopology;
use bevy_math::*;
use hexasphere::Hexasphere;

pub struct Cuboid {
pub min_x: f32,
pub max_x: f32,

pub min_y: f32,
pub max_y: f32,

pub min_z: f32,
pub max_z: f32,
}

impl Cuboid {
pub fn new(x_length: f32, y_length: f32, z_length: f32) -> Cuboid {
Cuboid {
max_x: x_length / 2.0,
min_x: -x_length / 2.0,
max_y: y_length / 2.0,
min_y: -y_length / 2.0,
max_z: z_length / 2.0,
min_z: -z_length / 2.0,
}
}
}

impl Default for Cuboid {
fn default() -> Self {
Cuboid::new(2.0, 1.0, 1.0)
}
}

impl From<Cuboid> for Mesh {
fn from(sp: Cuboid) -> Self {
let vertices = &[
// Top
([sp.min_x, sp.min_y, sp.max_z], [0., 0., 1.0], [0., 0.]),
([sp.max_x, sp.min_y, sp.max_z], [0., 0., 1.0], [1.0, 0.]),
([sp.max_x, sp.max_y, sp.max_z], [0., 0., 1.0], [1.0, 1.0]),
([sp.min_x, sp.max_y, sp.max_z], [0., 0., 1.0], [0., 1.0]),
// Bottom
([sp.min_x, sp.max_y, sp.min_z], [0., 0., -1.0], [1.0, 0.]),
([sp.max_x, sp.max_y, sp.min_z], [0., 0., -1.0], [0., 0.]),
([sp.max_x, sp.min_y, sp.min_z], [0., 0., -1.0], [0., 1.0]),
([sp.min_x, sp.min_y, sp.min_z], [0., 0., -1.0], [1.0, 1.0]),
// Right
([sp.max_x, sp.min_y, sp.min_z], [1.0, 0., 0.], [0., 0.]),
([sp.max_x, sp.max_y, sp.min_z], [1.0, 0., 0.], [1.0, 0.]),
([sp.max_x, sp.max_y, sp.max_z], [1.0, 0., 0.], [1.0, 1.0]),
([sp.max_x, sp.min_y, sp.max_z], [1.0, 0., 0.], [0., 1.0]),
// Left
([sp.min_x, sp.min_y, sp.max_z], [-1.0, 0., 0.], [1.0, 0.]),
([sp.min_x, sp.max_y, sp.max_z], [-1.0, 0., 0.], [0., 0.]),
([sp.min_x, sp.max_y, sp.min_z], [-1.0, 0., 0.], [0., 1.0]),
([sp.min_x, sp.min_y, sp.min_z], [-1.0, 0., 0.], [1.0, 1.0]),
// Front
([sp.max_x, sp.max_y, sp.min_z], [0., 1.0, 0.], [1.0, 0.]),
([sp.min_x, sp.max_y, sp.min_z], [0., 1.0, 0.], [0., 0.]),
([sp.min_x, sp.max_y, sp.max_z], [0., 1.0, 0.], [0., 1.0]),
([sp.max_x, sp.max_y, sp.max_z], [0., 1.0, 0.], [1.0, 1.0]),
// Back
([sp.max_x, sp.min_y, sp.max_z], [0., -1.0, 0.], [0., 0.]),
([sp.min_x, sp.min_y, sp.max_z], [0., -1.0, 0.], [1.0, 0.]),
([sp.min_x, sp.min_y, sp.min_z], [0., -1.0, 0.], [1.0, 1.0]),
([sp.max_x, sp.min_y, sp.min_z], [0., -1.0, 0.], [0., 1.0]),
];

let mut positions = Vec::with_capacity(24);
let mut normals = Vec::with_capacity(24);
let mut uvs = Vec::with_capacity(24);

for (position, normal, uv) in vertices.iter() {
positions.push(*position);
normals.push(*normal);
uvs.push(*uv);
}

let indices = Indices::U32(vec![
0, 1, 2, 2, 3, 0, // top
4, 5, 6, 6, 7, 4, // bottom
8, 9, 10, 10, 11, 8, // right
12, 13, 14, 14, 15, 12, // left
16, 17, 18, 18, 19, 16, // front
20, 21, 22, 22, 23, 20, // back
]);

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
mesh.set_indices(Some(indices));
mesh
}
}

/// A rectangle on the XY plane.
#[derive(Debug)]
pub struct Quad {
/// Full width and height of the rectangle.
pub size: Vec2,
/// Flips the texture coords of the resulting vertices.
pub flip: bool,
}

impl Quad {
pub fn new(size: Vec2) -> Self {
Self { size, flip: false }
}

pub fn flipped(size: Vec2) -> Self {
Self { size, flip: true }
}
}

impl From<Quad> for Mesh {
fn from(quad: Quad) -> Self {
let extent_x = quad.size.x / 2.0;
let extent_y = quad.size.y / 2.0;

let north_west = vec2(-extent_x, extent_y);
let north_east = vec2(extent_x, extent_y);
let south_west = vec2(-extent_x, -extent_y);
let south_east = vec2(extent_x, -extent_y);
let vertices = if quad.flip {
[
(
[south_east.x, south_east.y, 0.0],
[0.0, 0.0, 1.0],
[1.0, 1.0],
),
(
[north_east.x, north_east.y, 0.0],
[0.0, 0.0, 1.0],
[1.0, 0.0],
),
(
[north_west.x, north_west.y, 0.0],
[0.0, 0.0, 1.0],
[0.0, 0.0],
),
(
[south_west.x, south_west.y, 0.0],
[0.0, 0.0, 1.0],
[0.0, 1.0],
),
]
} else {
[
(
[south_west.x, south_west.y, 0.0],
[0.0, 0.0, 1.0],
[0.0, 1.0],
),
(
[north_west.x, north_west.y, 0.0],
[0.0, 0.0, 1.0],
[0.0, 0.0],
),
(
[north_east.x, north_east.y, 0.0],
[0.0, 0.0, 1.0],
[1.0, 0.0],
),
(
[south_east.x, south_east.y, 0.0],
[0.0, 0.0, 1.0],
[1.0, 1.0],
),
]
};

let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]);

let mut positions = Vec::<[f32; 3]>::new();
let mut normals = Vec::<[f32; 3]>::new();
let mut uvs = Vec::<[f32; 2]>::new();
for (position, normal, uv) in vertices.iter() {
positions.push(*position);
normals.push(*normal);
uvs.push(*uv);
}

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices));
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
mesh
}
}

/// A square on the XZ plane.
#[derive(Debug)]
pub struct Plane {
/// The total side length of the square.
pub size: f32,
}

impl From<Plane> for Mesh {
fn from(plane: Plane) -> Self {
let extent = plane.size / 2.0;

let vertices = [
([extent, 0.0, -extent], [0.0, 1.0, 0.0], [1.0, 1.0]),
([extent, 0.0, extent], [0.0, 1.0, 0.0], [1.0, 0.0]),
([-extent, 0.0, extent], [0.0, 1.0, 0.0], [0.0, 0.0]),
([-extent, 0.0, -extent], [0.0, 1.0, 0.0], [0.0, 1.0]),
];

let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]);

let mut positions = Vec::new();
let mut normals = Vec::new();
let mut uvs = Vec::new();
for (position, normal, uv) in vertices.iter() {
positions.push(*position);
normals.push(*normal);
uvs.push(*uv);
}

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices));
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
mesh
}
}

/// A sphere made from a subdivided Icosahedron.
#[derive(Debug)]
pub struct Icosphere {
/// The radius of the sphere.
pub radius: f32,
/// The number of subdivisions applied.
pub subdivisions: usize,
}

impl Default for Icosphere {
fn default() -> Self {
Self {
radius: 1.0,
subdivisions: 5,
}
}
}

impl From<Icosphere> for Mesh {
fn from(sphere: Icosphere) -> Self {
if sphere.subdivisions >= 80 {
let temp_sphere = Hexasphere::new(sphere.subdivisions, |_| ());

panic!(
"Cannot create an icosphere of {} subdivisions due to there being too many vertices being generated: {} (Limited to 65535 vertices or 79 subdivisions)",
sphere.subdivisions,
temp_sphere.raw_points().len()
);
}
let hexasphere = Hexasphere::new(sphere.subdivisions, |point| {
let inclination = point.z.acos();
let azumith = point.y.atan2(point.x);

let norm_inclination = 1.0 - (inclination / std::f32::consts::PI);
let norm_azumith = (azumith / std::f32::consts::PI) * 0.5;

[norm_inclination, norm_azumith]
});

let raw_points = hexasphere.raw_points();

let points = raw_points
.iter()
.map(|&p| (p * sphere.radius).into())
.collect::<Vec<[f32; 3]>>();

let normals = raw_points
.iter()
.copied()
.map(Into::into)
.collect::<Vec<[f32; 3]>>();

let uvs = hexasphere.raw_data().to_owned();

let mut indices = Vec::with_capacity(hexasphere.indices_per_main_triangle() * 20);

for i in 0..20 {
hexasphere.get_indices(i, &mut indices);
}

let indices = Indices::U32(indices);

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices));
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, points);
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
mesh
}
}
}

fn remove_resource_save(
render_resource_context: &dyn RenderResourceContext,
handle: &Handle<Mesh>,
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_render/src/mesh/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[allow(clippy::module_inception)]
mod mesh;
/// Generation for some primitive shape meshes.
pub mod shape;

pub use mesh::*;
Loading

0 comments on commit b95c518

Please sign in to comment.