mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Add box shape (#883)
* Add rectangular cuboid shape Co-authored-by: Jason Lessard <jason.lessard@usherbrooke.ca> Co-authored-by: Jason Lessard <jason.lessard@usherbrooke.ca> Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
0dbbcd98b6
commit
d458406540
12 changed files with 341 additions and 304 deletions
|
@ -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>,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#[allow(clippy::module_inception)]
|
||||
mod mesh;
|
||||
/// Generation for some primitive shape meshes.
|
||||
pub mod shape;
|
||||
|
||||
pub use mesh::*;
|
||||
|
|
324
crates/bevy_render/src/mesh/shape.rs
Normal file
324
crates/bevy_render/src/mesh/shape.rs
Normal file
|
@ -0,0 +1,324 @@
|
|||
use super::{Indices, Mesh};
|
||||
use crate::pipeline::PrimitiveTopology;
|
||||
use bevy_math::*;
|
||||
use hexasphere::Hexasphere;
|
||||
|
||||
pub struct Cube {
|
||||
pub size: f32,
|
||||
}
|
||||
|
||||
impl Cube {
|
||||
pub fn new(size: f32) -> Cube {
|
||||
Cube { size }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Cube {
|
||||
fn default() -> Self {
|
||||
Cube { size: 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Cube> for Mesh {
|
||||
fn from(cube: Cube) -> Self {
|
||||
Box::new(cube.size, cube.size, cube.size).into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Box {
|
||||
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 Box {
|
||||
pub fn new(x_length: f32, y_length: f32, z_length: f32) -> Box {
|
||||
Box {
|
||||
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 Box {
|
||||
fn default() -> Self {
|
||||
Box::new(2.0, 1.0, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box> for Mesh {
|
||||
fn from(sp: Box) -> 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
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ fn setup(
|
|||
commands
|
||||
// plane
|
||||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })),
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -26,7 +26,7 @@ fn setup(
|
|||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 1.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.5, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
|
@ -36,7 +36,7 @@ fn setup(
|
|||
})
|
||||
// camera
|
||||
.spawn(Camera3dBundle {
|
||||
transform: Transform::from_translation(Vec3::new(-3.0, 5.0, 8.0))
|
||||
transform: Transform::from_translation(Vec3::new(-2.0, 2.5, 5.0))
|
||||
.looking_at(Vec3::default(), Vec3::unit_y()),
|
||||
..Default::default()
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ fn setup(
|
|||
commands
|
||||
// cube
|
||||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 2.0 })),
|
||||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||
..Default::default()
|
||||
})
|
||||
|
|
|
@ -27,7 +27,7 @@ fn setup(
|
|||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 }));
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 2.0 }));
|
||||
let cube_material_handle = materials.add(StandardMaterial {
|
||||
albedo: Color::rgb(0.8, 0.7, 0.6),
|
||||
..Default::default()
|
||||
|
|
|
@ -46,7 +46,7 @@ fn setup(
|
|||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 }));
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 2.0 }));
|
||||
commands
|
||||
// parent cube
|
||||
.spawn(PbrBundle {
|
||||
|
|
|
@ -20,7 +20,7 @@ fn setup(
|
|||
commands
|
||||
// plane
|
||||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })),
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -28,7 +28,7 @@ fn setup(
|
|||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 1.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.5, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
|
@ -38,7 +38,7 @@ fn setup(
|
|||
})
|
||||
// camera
|
||||
.spawn(Camera3dBundle {
|
||||
transform: Transform::from_translation(Vec3::new(-3.0, 5.0, 8.0))
|
||||
transform: Transform::from_translation(Vec3::new(-2.0, 2.5, 5.0))
|
||||
.looking_at(Vec3::default(), Vec3::unit_y()),
|
||||
..Default::default()
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ fn setup(
|
|||
commands
|
||||
// plane
|
||||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })),
|
||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||
material: materials.add(Color::rgb(0.1, 0.2, 0.1).into()),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -33,7 +33,7 @@ fn setup(
|
|||
.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 1.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.5, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// sphere
|
||||
|
@ -53,7 +53,7 @@ fn setup(
|
|||
})
|
||||
// camera
|
||||
.spawn(Camera3dBundle {
|
||||
transform: Transform::from_translation(Vec3::new(-3.0, 5.0, 8.0))
|
||||
transform: Transform::from_translation(Vec3::new(-2.0, 2.5, 5.0))
|
||||
.looking_at(Vec3::default(), Vec3::unit_y()),
|
||||
..Default::default()
|
||||
});
|
||||
|
|
|
@ -83,7 +83,7 @@ fn setup(
|
|||
let material = materials.add(MyMaterialWithVertexColorSupport {});
|
||||
|
||||
// create a generic cube
|
||||
let mut cube_with_vertex_colors = Mesh::from(shape::Cube { size: 1.0 });
|
||||
let mut cube_with_vertex_colors = Mesh::from(shape::Cube { size: 2.0 });
|
||||
|
||||
// insert our custom color attribute with some nice colors!
|
||||
cube_with_vertex_colors.set_attribute(
|
||||
|
|
|
@ -84,7 +84,7 @@ fn setup(
|
|||
commands
|
||||
// cube
|
||||
.spawn(MeshBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 2.0 })),
|
||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||
pipeline_handle,
|
||||
)]),
|
||||
|
|
|
@ -97,7 +97,7 @@ fn setup(
|
|||
});
|
||||
|
||||
// Create a cube mesh which will use our materials
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 }));
|
||||
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 2.0 }));
|
||||
|
||||
commands
|
||||
// cube
|
||||
|
|
Loading…
Reference in a new issue