use bevy::prelude::*;
use bevy::render::mesh::{Indices, PrimitiveTopology};
use bevy::render::render_asset::RenderAssetUsages;
use bevy_rapier3d::prelude::*;
pub fn create_d4() -> (Mesh, Collider, Vec<(Vec3, u32)>) {
let size = 0.5;
let a = size; let h = a * (2.0_f32 / 3.0_f32).sqrt();
let base_y = -h / 4.0;
let apex_y = 3.0 * h / 4.0;
let base_r = a / (3.0_f32).sqrt();
let v0 = Vec3::new(0.0, apex_y, 0.0); let v1 = Vec3::new(0.0, base_y, base_r); let v2 = Vec3::new(base_r * 0.866, base_y, -base_r * 0.5); let v3 = Vec3::new(-base_r * 0.866, base_y, -base_r * 0.5);
let vertices = vec![v0, v1, v2, v3];
let face_normals = vec![
(v0.normalize(), 1), (v3.normalize(), 2), (v1.normalize(), 3), (v2.normalize(), 4), ];
let mesh_n_base = (v2 - v1).cross(v3 - v1).normalize();
let mesh_n_front = (v1 - v0).cross(v2 - v0).normalize();
let mesh_n_right = (v2 - v0).cross(v3 - v0).normalize();
let mesh_n_left = (v3 - v0).cross(v1 - v0).normalize();
let positions: Vec<[f32; 3]> = vec![
v1.into(),
v2.into(),
v3.into(),
v0.into(),
v1.into(),
v2.into(),
v0.into(),
v2.into(),
v3.into(),
v0.into(),
v3.into(),
v1.into(),
];
let normals: Vec<[f32; 3]> = vec![
mesh_n_base.into(),
mesh_n_base.into(),
mesh_n_base.into(),
mesh_n_front.into(),
mesh_n_front.into(),
mesh_n_front.into(),
mesh_n_right.into(),
mesh_n_right.into(),
mesh_n_right.into(),
mesh_n_left.into(),
mesh_n_left.into(),
mesh_n_left.into(),
];
let uvs: Vec<[f32; 2]> = vec![
[0.5, 0.0],
[0.0, 1.0],
[1.0, 1.0],
[0.5, 0.0],
[0.0, 1.0],
[1.0, 1.0],
[0.5, 0.0],
[0.0, 1.0],
[1.0, 1.0],
[0.5, 0.0],
[0.0, 1.0],
[1.0, 1.0],
];
let indices: Vec<u32> = (0..12).collect();
let mesh = 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));
let collider = Collider::convex_hull(&vertices).unwrap_or(Collider::ball(size / 2.0));
(mesh, collider, face_normals)
}
pub fn get_d4_number_positions() -> Vec<(Vec3, Quat, u32)> {
let size = 0.5;
let a = size;
let h = a * (2.0_f32 / 3.0_f32).sqrt();
let base_y = -h / 4.0;
let apex_y = 3.0 * h / 4.0;
let base_r = a / (3.0_f32).sqrt();
let v0 = Vec3::new(0.0, apex_y, 0.0); let v1 = Vec3::new(0.0, base_y, base_r); let v2 = Vec3::new(base_r * 0.866, base_y, -base_r * 0.5); let v3 = Vec3::new(-base_r * 0.866, base_y, -base_r * 0.5);
let face_a_center = (v1 + v2 + v3) / 3.0; let face_b_center = (v0 + v1 + v2) / 3.0; let face_c_center = (v0 + v2 + v3) / 3.0; let face_d_center = (v0 + v3 + v1) / 3.0;
let n_a = (v2 - v1).cross(v3 - v1).normalize(); let n_b = (v1 - v0).cross(v2 - v0).normalize();
let n_c = (v2 - v0).cross(v3 - v0).normalize();
let n_d = (v3 - v0).cross(v1 - v0).normalize();
let label_offset_from_center = 0.07; let surface_offset = 0.008;
let mut positions = Vec::new();
let calc_rotation =
|face_normal: Vec3, _face_center: Vec3, number_pos: Vec3, target_vertex: Vec3| -> Quat {
let z_axis = face_normal;
let to_vertex = target_vertex - number_pos;
let y_axis = (to_vertex - face_normal * to_vertex.dot(face_normal)).normalize();
let x_axis = y_axis.cross(z_axis).normalize();
Quat::from_mat3(&bevy::math::Mat3::from_cols(x_axis, y_axis, z_axis))
};
let pos_a1 = face_a_center
+ (v1 - face_a_center).normalize() * label_offset_from_center
+ n_a * surface_offset;
let pos_a2 = face_a_center
+ (v2 - face_a_center).normalize() * label_offset_from_center
+ n_a * surface_offset;
let pos_a3 = face_a_center
+ (v3 - face_a_center).normalize() * label_offset_from_center
+ n_a * surface_offset;
let flip_y = Quat::from_rotation_y(std::f32::consts::PI);
let rot_a1 = calc_rotation(n_a, face_a_center, pos_a1, v1) * flip_y;
let rot_a2 = calc_rotation(n_a, face_a_center, pos_a2, v2) * flip_y;
let rot_a3 = calc_rotation(n_a, face_a_center, pos_a3, v3) * flip_y;
positions.push((pos_a1, rot_a1, 3)); positions.push((pos_a2, rot_a2, 4)); positions.push((pos_a3, rot_a3, 2));
let pos_b0 = face_b_center
+ (v0 - face_b_center).normalize() * label_offset_from_center
+ n_b * surface_offset;
let pos_b1 = face_b_center
+ (v1 - face_b_center).normalize() * label_offset_from_center
+ n_b * surface_offset;
let pos_b2 = face_b_center
+ (v2 - face_b_center).normalize() * label_offset_from_center
+ n_b * surface_offset;
let rot_b0 = calc_rotation(n_b, face_b_center, pos_b0, v0);
let rot_b1 = calc_rotation(n_b, face_b_center, pos_b1, v1);
let rot_b2 = calc_rotation(n_b, face_b_center, pos_b2, v2);
positions.push((pos_b0, rot_b0, 1)); positions.push((pos_b1, rot_b1, 3)); positions.push((pos_b2, rot_b2, 4));
let pos_c0 = face_c_center
+ (v0 - face_c_center).normalize() * label_offset_from_center
+ n_c * surface_offset;
let pos_c2 = face_c_center
+ (v2 - face_c_center).normalize() * label_offset_from_center
+ n_c * surface_offset;
let pos_c3 = face_c_center
+ (v3 - face_c_center).normalize() * label_offset_from_center
+ n_c * surface_offset;
let rot_c0 = calc_rotation(n_c, face_c_center, pos_c0, v0);
let rot_c2 = calc_rotation(n_c, face_c_center, pos_c2, v2);
let rot_c3 = calc_rotation(n_c, face_c_center, pos_c3, v3);
positions.push((pos_c0, rot_c0, 1)); positions.push((pos_c2, rot_c2, 4)); positions.push((pos_c3, rot_c3, 2));
let pos_d0 = face_d_center
+ (v0 - face_d_center).normalize() * label_offset_from_center
+ n_d * surface_offset;
let pos_d3 = face_d_center
+ (v3 - face_d_center).normalize() * label_offset_from_center
+ n_d * surface_offset;
let pos_d1 = face_d_center
+ (v1 - face_d_center).normalize() * label_offset_from_center
+ n_d * surface_offset;
let rot_d0 = calc_rotation(n_d, face_d_center, pos_d0, v0);
let rot_d3 = calc_rotation(n_d, face_d_center, pos_d3, v3);
let rot_d1 = calc_rotation(n_d, face_d_center, pos_d1, v1);
positions.push((pos_d0, rot_d0, 1)); positions.push((pos_d3, rot_d3, 2)); positions.push((pos_d1, rot_d1, 3));
positions
}