Skip to content

Commit d458406

Browse files
e00EJason Lessardcart
authored
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>
1 parent 0dbbcd9 commit d458406

File tree

12 files changed

+341
-304
lines changed

12 files changed

+341
-304
lines changed

crates/bevy_render/src/mesh/mesh.rs

-289
Original file line numberDiff line numberDiff line change
@@ -220,295 +220,6 @@ impl Mesh {
220220
}
221221
}
222222

223-
/// Generation for some primitive shape meshes.
224-
pub mod shape {
225-
use super::{Indices, Mesh};
226-
use crate::pipeline::PrimitiveTopology;
227-
use bevy_math::*;
228-
use hexasphere::Hexasphere;
229-
230-
/// A cube.
231-
#[derive(Debug)]
232-
pub struct Cube {
233-
/// Half the side length of the cube.
234-
pub size: f32,
235-
}
236-
237-
impl Default for Cube {
238-
fn default() -> Self {
239-
Cube { size: 1.0 }
240-
}
241-
}
242-
243-
impl From<Cube> for Mesh {
244-
fn from(cube: Cube) -> Self {
245-
let size = cube.size;
246-
let vertices = &[
247-
// top (0., 0., size)
248-
([-size, -size, size], [0., 0., size], [0., 0.]),
249-
([size, -size, size], [0., 0., size], [size, 0.]),
250-
([size, size, size], [0., 0., size], [size, size]),
251-
([-size, size, size], [0., 0., size], [0., size]),
252-
// bottom (0., 0., -size)
253-
([-size, size, -size], [0., 0., -size], [size, 0.]),
254-
([size, size, -size], [0., 0., -size], [0., 0.]),
255-
([size, -size, -size], [0., 0., -size], [0., size]),
256-
([-size, -size, -size], [0., 0., -size], [size, size]),
257-
// right (size, 0., 0.)
258-
([size, -size, -size], [size, 0., 0.], [0., 0.]),
259-
([size, size, -size], [size, 0., 0.], [size, 0.]),
260-
([size, size, size], [size, 0., 0.], [size, size]),
261-
([size, -size, size], [size, 0., 0.], [0., size]),
262-
// left (-size, 0., 0.)
263-
([-size, -size, size], [-size, 0., 0.], [size, 0.]),
264-
([-size, size, size], [-size, 0., 0.], [0., 0.]),
265-
([-size, size, -size], [-size, 0., 0.], [0., size]),
266-
([-size, -size, -size], [-size, 0., 0.], [size, size]),
267-
// front (0., size, 0.)
268-
([size, size, -size], [0., size, 0.], [size, 0.]),
269-
([-size, size, -size], [0., size, 0.], [0., 0.]),
270-
([-size, size, size], [0., size, 0.], [0., size]),
271-
([size, size, size], [0., size, 0.], [size, size]),
272-
// back (0., -size, 0.)
273-
([size, -size, size], [0., -size, 0.], [0., 0.]),
274-
([-size, -size, size], [0., -size, 0.], [size, 0.]),
275-
([-size, -size, -size], [0., -size, 0.], [size, size]),
276-
([size, -size, -size], [0., -size, 0.], [0., size]),
277-
];
278-
279-
let mut positions = Vec::new();
280-
let mut normals = Vec::new();
281-
let mut uvs = Vec::new();
282-
for (position, normal, uv) in vertices.iter() {
283-
positions.push(*position);
284-
normals.push(*normal);
285-
uvs.push(*uv);
286-
}
287-
288-
let indices = Indices::U32(vec![
289-
0, 1, 2, 2, 3, 0, // top
290-
4, 5, 6, 6, 7, 4, // bottom
291-
8, 9, 10, 10, 11, 8, // right
292-
12, 13, 14, 14, 15, 12, // left
293-
16, 17, 18, 18, 19, 16, // front
294-
20, 21, 22, 22, 23, 20, // back
295-
]);
296-
297-
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
298-
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
299-
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
300-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
301-
mesh.set_indices(Some(indices));
302-
mesh
303-
}
304-
}
305-
306-
/// A rectangle on the XY plane.
307-
#[derive(Debug)]
308-
pub struct Quad {
309-
/// Full width and height of the rectangle.
310-
pub size: Vec2,
311-
/// Flips the texture coords of the resulting vertices.
312-
pub flip: bool,
313-
}
314-
315-
impl Quad {
316-
pub fn new(size: Vec2) -> Self {
317-
Self { size, flip: false }
318-
}
319-
320-
pub fn flipped(size: Vec2) -> Self {
321-
Self { size, flip: true }
322-
}
323-
}
324-
325-
impl From<Quad> for Mesh {
326-
fn from(quad: Quad) -> Self {
327-
let extent_x = quad.size.x / 2.0;
328-
let extent_y = quad.size.y / 2.0;
329-
330-
let north_west = vec2(-extent_x, extent_y);
331-
let north_east = vec2(extent_x, extent_y);
332-
let south_west = vec2(-extent_x, -extent_y);
333-
let south_east = vec2(extent_x, -extent_y);
334-
let vertices = if quad.flip {
335-
[
336-
(
337-
[south_east.x, south_east.y, 0.0],
338-
[0.0, 0.0, 1.0],
339-
[1.0, 1.0],
340-
),
341-
(
342-
[north_east.x, north_east.y, 0.0],
343-
[0.0, 0.0, 1.0],
344-
[1.0, 0.0],
345-
),
346-
(
347-
[north_west.x, north_west.y, 0.0],
348-
[0.0, 0.0, 1.0],
349-
[0.0, 0.0],
350-
),
351-
(
352-
[south_west.x, south_west.y, 0.0],
353-
[0.0, 0.0, 1.0],
354-
[0.0, 1.0],
355-
),
356-
]
357-
} else {
358-
[
359-
(
360-
[south_west.x, south_west.y, 0.0],
361-
[0.0, 0.0, 1.0],
362-
[0.0, 1.0],
363-
),
364-
(
365-
[north_west.x, north_west.y, 0.0],
366-
[0.0, 0.0, 1.0],
367-
[0.0, 0.0],
368-
),
369-
(
370-
[north_east.x, north_east.y, 0.0],
371-
[0.0, 0.0, 1.0],
372-
[1.0, 0.0],
373-
),
374-
(
375-
[south_east.x, south_east.y, 0.0],
376-
[0.0, 0.0, 1.0],
377-
[1.0, 1.0],
378-
),
379-
]
380-
};
381-
382-
let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]);
383-
384-
let mut positions = Vec::<[f32; 3]>::new();
385-
let mut normals = Vec::<[f32; 3]>::new();
386-
let mut uvs = Vec::<[f32; 2]>::new();
387-
for (position, normal, uv) in vertices.iter() {
388-
positions.push(*position);
389-
normals.push(*normal);
390-
uvs.push(*uv);
391-
}
392-
393-
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
394-
mesh.set_indices(Some(indices));
395-
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
396-
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
397-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
398-
mesh
399-
}
400-
}
401-
402-
/// A square on the XZ plane.
403-
#[derive(Debug)]
404-
pub struct Plane {
405-
/// The total side length of the square.
406-
pub size: f32,
407-
}
408-
409-
impl From<Plane> for Mesh {
410-
fn from(plane: Plane) -> Self {
411-
let extent = plane.size / 2.0;
412-
413-
let vertices = [
414-
([extent, 0.0, -extent], [0.0, 1.0, 0.0], [1.0, 1.0]),
415-
([extent, 0.0, extent], [0.0, 1.0, 0.0], [1.0, 0.0]),
416-
([-extent, 0.0, extent], [0.0, 1.0, 0.0], [0.0, 0.0]),
417-
([-extent, 0.0, -extent], [0.0, 1.0, 0.0], [0.0, 1.0]),
418-
];
419-
420-
let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]);
421-
422-
let mut positions = Vec::new();
423-
let mut normals = Vec::new();
424-
let mut uvs = Vec::new();
425-
for (position, normal, uv) in vertices.iter() {
426-
positions.push(*position);
427-
normals.push(*normal);
428-
uvs.push(*uv);
429-
}
430-
431-
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
432-
mesh.set_indices(Some(indices));
433-
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, positions);
434-
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
435-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
436-
mesh
437-
}
438-
}
439-
440-
/// A sphere made from a subdivided Icosahedron.
441-
#[derive(Debug)]
442-
pub struct Icosphere {
443-
/// The radius of the sphere.
444-
pub radius: f32,
445-
/// The number of subdivisions applied.
446-
pub subdivisions: usize,
447-
}
448-
449-
impl Default for Icosphere {
450-
fn default() -> Self {
451-
Self {
452-
radius: 1.0,
453-
subdivisions: 5,
454-
}
455-
}
456-
}
457-
458-
impl From<Icosphere> for Mesh {
459-
fn from(sphere: Icosphere) -> Self {
460-
if sphere.subdivisions >= 80 {
461-
let temp_sphere = Hexasphere::new(sphere.subdivisions, |_| ());
462-
463-
panic!(
464-
"Cannot create an icosphere of {} subdivisions due to there being too many vertices being generated: {} (Limited to 65535 vertices or 79 subdivisions)",
465-
sphere.subdivisions,
466-
temp_sphere.raw_points().len()
467-
);
468-
}
469-
let hexasphere = Hexasphere::new(sphere.subdivisions, |point| {
470-
let inclination = point.z.acos();
471-
let azumith = point.y.atan2(point.x);
472-
473-
let norm_inclination = 1.0 - (inclination / std::f32::consts::PI);
474-
let norm_azumith = (azumith / std::f32::consts::PI) * 0.5;
475-
476-
[norm_inclination, norm_azumith]
477-
});
478-
479-
let raw_points = hexasphere.raw_points();
480-
481-
let points = raw_points
482-
.iter()
483-
.map(|&p| (p * sphere.radius).into())
484-
.collect::<Vec<[f32; 3]>>();
485-
486-
let normals = raw_points
487-
.iter()
488-
.copied()
489-
.map(Into::into)
490-
.collect::<Vec<[f32; 3]>>();
491-
492-
let uvs = hexasphere.raw_data().to_owned();
493-
494-
let mut indices = Vec::with_capacity(hexasphere.indices_per_main_triangle() * 20);
495-
496-
for i in 0..20 {
497-
hexasphere.get_indices(i, &mut indices);
498-
}
499-
500-
let indices = Indices::U32(indices);
501-
502-
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
503-
mesh.set_indices(Some(indices));
504-
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, points);
505-
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
506-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
507-
mesh
508-
}
509-
}
510-
}
511-
512223
fn remove_resource_save(
513224
render_resource_context: &dyn RenderResourceContext,
514225
handle: &Handle<Mesh>,

crates/bevy_render/src/mesh/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#[allow(clippy::module_inception)]
22
mod mesh;
3+
/// Generation for some primitive shape meshes.
4+
pub mod shape;
35

46
pub use mesh::*;

0 commit comments

Comments
 (0)