Skip to content

Commit

Permalink
use MIT licensed torus generation code
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobhellermann committed Jan 8, 2021
1 parent f8e3a99 commit a3241b4
Showing 1 changed file with 36 additions and 38 deletions.
74 changes: 36 additions & 38 deletions crates/bevy_render/src/mesh/shape/torus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::{
mesh::{Indices, Mesh},
pipeline::PrimitiveTopology,
};
use bevy_math::{Quat, Vec3};
use bevy_math::Vec3;

/// A torus (donut) shape.
#[derive(Debug)]
pub struct Torus {
pub radius: f32,
pub tube_radius: f32,
pub ring_radius: f32,
pub subdivisions_segments: usize,
pub subdivisions_sides: usize,
}
Expand All @@ -17,7 +17,7 @@ impl Default for Torus {
fn default() -> Self {
Torus {
radius: 1.0,
tube_radius: 0.5,
ring_radius: 0.5,
subdivisions_segments: 32,
subdivisions_sides: 24,
}
Expand All @@ -26,63 +26,61 @@ impl Default for Torus {

impl From<Torus> for Mesh {
fn from(torus: Torus) -> Self {
// code adapted from http://wiki.unity3d.com/index.php/ProceduralPrimitives#C.23_-_Torus
// code adapted from http://apparat-engine.blogspot.com/2013/04/procedural-meshes-torus.html
// (source code at https://github.com/SEilers/Apparat)

let n_vertices = (torus.subdivisions_segments + 1) * (torus.subdivisions_sides + 1);
let mut positions: Vec<[f32; 3]> = Vec::with_capacity(n_vertices);
let mut normals: Vec<[f32; 3]> = Vec::with_capacity(n_vertices);
let mut uvs: Vec<[f32; 2]> = Vec::with_capacity(n_vertices);

let segment_stride = 2.0 * std::f32::consts::PI / torus.subdivisions_segments as f32;
let side_stride = 2.0 * std::f32::consts::PI / torus.subdivisions_sides as f32;

for segment in 0..=torus.subdivisions_segments {
let t1 =
segment as f32 / torus.subdivisions_segments as f32 * 2.0 * std::f32::consts::PI;
let r1 = Vec3::new(t1.cos() * torus.radius, 0.0, t1.sin() * torus.radius);
let theta = segment_stride * segment as f32;
let segment_pos = Vec3::new(theta.cos(), 0.0, theta.sin() * torus.radius);

for side in 0..=torus.subdivisions_sides {
let t2 = side as f32 / torus.subdivisions_sides as f32 * 2.0 * std::f32::consts::PI;
let r2 = Quat::from_axis_angle(Vec3::unit_y(), -t1)
* Vec3::new(
t2.sin() * torus.tube_radius,
t2.cos() * torus.tube_radius,
0.0,
);

let position = r1 + r2;
let normal = r1.cross(Vec3::unit_y()).normalize();
let uv = [
segment as f32 / torus.subdivisions_segments as f32,
side as f32 / torus.subdivisions_sides as f32,
];
let phi = side_stride * side as f32;

let x = theta.cos() * (torus.radius + torus.ring_radius * phi.cos());
let z = theta.sin() * (torus.radius + torus.ring_radius * phi.cos());
let y = torus.ring_radius * phi.sin();

positions.push(position.into());
let normal = segment_pos.cross(Vec3::unit_y()).normalize();

positions.push([x, y, z]);
normals.push(normal.into());
uvs.push(uv);
uvs.push([
segment as f32 / torus.subdivisions_segments as f32,
side as f32 / torus.subdivisions_sides as f32,
]);
}
}

let n_faces = (torus.subdivisions_segments + 1) * (torus.subdivisions_sides);
let n_faces = (torus.subdivisions_segments) * (torus.subdivisions_sides);
let n_triangles = n_faces * 2;
let n_indices = n_triangles * 3;

let mut indices: Vec<u32> = Vec::with_capacity(n_indices);

for segment in 0..=torus.subdivisions_segments as u32 {
for side in 0..torus.subdivisions_sides as u32 {
let current = side + segment * (torus.subdivisions_sides as u32 + 1);
let n_vertices_per_row = torus.subdivisions_sides + 1;
for segment in 0..torus.subdivisions_segments {
for side in 0..torus.subdivisions_sides {
let lt = side + segment * n_vertices_per_row;
let rt = (side + 1) + segment * n_vertices_per_row;

let next = if segment < torus.subdivisions_segments as u32 {
(segment + 1) * (torus.subdivisions_sides as u32 + 1)
} else {
0
} + side;
let lb = side + (segment + 1) * n_vertices_per_row;
let rb = (side + 1) + (segment + 1) * n_vertices_per_row;

indices.push(current);
indices.push(next);
indices.push(next + 1);
indices.push(lt as u32);
indices.push(rt as u32);
indices.push(lb as u32);

indices.push(current);
indices.push(next + 1);
indices.push(current + 1);
indices.push(rt as u32);
indices.push(rb as u32);
indices.push(lb as u32);
}
}

Expand Down

0 comments on commit a3241b4

Please sign in to comment.