use bevy::prelude::*;
use bevy::render::mesh::{Indices, PrimitiveTopology};
use bevy::render::render_asset::RenderAssetUsages;
use bevy_rapier3d::prelude::*;
pub fn create_d10() -> (Mesh, Collider, Vec<(Vec3, u32)>) {
let size = 0.5;
let angle = std::f32::consts::PI / 5.0;
let mut vertices = Vec::new();
let top = Vec3::new(0.0, size * 0.9, 0.0);
let bottom = Vec3::new(0.0, -size * 0.9, 0.0);
vertices.push(top);
vertices.push(bottom);
let mut upper_ring = Vec::new();
for i in 0..5 {
let a = i as f32 * angle * 2.0;
let v = Vec3::new(a.cos() * size * 0.7, size * 0.3, a.sin() * size * 0.7);
upper_ring.push(v);
vertices.push(v);
}
let mut lower_ring = Vec::new();
for i in 0..5 {
let a = (i as f32 + 0.5) * angle * 2.0;
let v = Vec3::new(a.cos() * size * 0.7, -size * 0.3, a.sin() * size * 0.7);
lower_ring.push(v);
vertices.push(v);
}
let mut face_normals: Vec<(Vec3, u32)> = Vec::new();
for i in 0..5 {
let next = (i + 1) % 5;
let upper_face_center = (top + upper_ring[i] + lower_ring[i] + upper_ring[next]) / 4.0;
face_normals.push((upper_face_center.normalize(), (i * 2 + 1) as u32));
let lower_face_center =
(bottom + lower_ring[next] + upper_ring[next] + lower_ring[i]) / 4.0;
face_normals.push((lower_face_center.normalize(), (i * 2 + 2) as u32));
}
let collider = Collider::convex_hull(&vertices).unwrap_or(Collider::ball(size));
let mesh = create_d10_mesh(size);
(mesh, collider, face_normals)
}
fn create_d10_mesh(size: f32) -> Mesh {
let angle = std::f32::consts::PI / 5.0;
let top = [0.0, size * 0.9, 0.0];
let bottom = [0.0, -size * 0.9, 0.0];
let mut upper_ring = Vec::new();
for i in 0..5 {
let a = i as f32 * angle * 2.0;
upper_ring.push([a.cos() * size * 0.7, size * 0.3, a.sin() * size * 0.7]);
}
let mut lower_ring = Vec::new();
for i in 0..5 {
let a = (i as f32 + 0.5) * angle * 2.0;
lower_ring.push([a.cos() * size * 0.7, -size * 0.3, a.sin() * size * 0.7]);
}
let mut positions = Vec::new();
let mut normals = Vec::new();
for i in 0..5 {
let next = (i + 1) % 5;
positions.push(top);
positions.push(upper_ring[i]);
positions.push(lower_ring[i]);
positions.push(top);
positions.push(lower_ring[i]);
positions.push(upper_ring[next]);
let v1 = Vec3::from_array(upper_ring[i]) - Vec3::from_array(top);
let v2 = Vec3::from_array(lower_ring[i]) - Vec3::from_array(top);
let n = v1.cross(v2).normalize();
for _ in 0..6 {
normals.push(n.to_array());
}
positions.push(bottom);
positions.push(lower_ring[next]);
positions.push(upper_ring[next]);
positions.push(bottom);
positions.push(upper_ring[next]);
positions.push(lower_ring[i]);
let v1 = Vec3::from_array(lower_ring[next]) - Vec3::from_array(bottom);
let v2 = Vec3::from_array(upper_ring[next]) - Vec3::from_array(bottom);
let n = v1.cross(v2).normalize();
for _ in 0..6 {
normals.push(n.to_array());
}
}
let num_vertices = positions.len();
let indices: Vec<u32> = (0..num_vertices as u32).collect();
let uvs: Vec<[f32; 2]> = positions.iter().map(|_| [0.5, 0.5]).collect();
Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
.with_inserted_indices(Indices::U32(indices))
}