Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rectangular cuboid shape #883

Merged
merged 2 commits into from
Nov 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 0 additions & 289 deletions crates/bevy_render/src/mesh/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,295 +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;

/// A cube.
#[derive(Debug)]
pub struct Cube {
/// Half the side length of the cube.
pub size: f32,
}

impl Default for Cube {
fn default() -> Self {
Cube { size: 1.0 }
}
}

impl From<Cube> for Mesh {
fn from(cube: Cube) -> Self {
let size = cube.size;
let vertices = &[
// top (0., 0., size)
([-size, -size, size], [0., 0., size], [0., 0.]),
([size, -size, size], [0., 0., size], [size, 0.]),
([size, size, size], [0., 0., size], [size, size]),
([-size, size, size], [0., 0., size], [0., size]),
// bottom (0., 0., -size)
([-size, size, -size], [0., 0., -size], [size, 0.]),
([size, size, -size], [0., 0., -size], [0., 0.]),
([size, -size, -size], [0., 0., -size], [0., size]),
([-size, -size, -size], [0., 0., -size], [size, size]),
// right (size, 0., 0.)
([size, -size, -size], [size, 0., 0.], [0., 0.]),
([size, size, -size], [size, 0., 0.], [size, 0.]),
([size, size, size], [size, 0., 0.], [size, size]),
([size, -size, size], [size, 0., 0.], [0., size]),
// left (-size, 0., 0.)
([-size, -size, size], [-size, 0., 0.], [size, 0.]),
([-size, size, size], [-size, 0., 0.], [0., 0.]),
([-size, size, -size], [-size, 0., 0.], [0., size]),
([-size, -size, -size], [-size, 0., 0.], [size, size]),
// front (0., size, 0.)
([size, size, -size], [0., size, 0.], [size, 0.]),
([-size, size, -size], [0., size, 0.], [0., 0.]),
([-size, size, size], [0., size, 0.], [0., size]),
([size, size, size], [0., size, 0.], [size, size]),
// back (0., -size, 0.)
([size, -size, size], [0., -size, 0.], [0., 0.]),
([-size, -size, size], [0., -size, 0.], [size, 0.]),
([-size, -size, -size], [0., -size, 0.], [size, size]),
([size, -size, -size], [0., -size, 0.], [0., size]),
];

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 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