use core::f32;
use bevy_transform::{components::Transform, TransformPoint};
use glam::{Vec2, Vec3};
use slotmap::SecondaryMap;
use crate::mesh::{
attributes::{SelectionQueries, TraversalQueries},
HalfEdgeId, HalfEdgeMesh,
};
pub(crate) fn sphere(mesh: &mut HalfEdgeMesh, sphere_center: Vec3, sphere_radius: Vec3) {
let mut uvmap = SecondaryMap::<HalfEdgeId, Vec2>::new();
for edge in mesh.edge_keys() {
let d = (mesh.goto(edge).position() - sphere_center) / sphere_radius;
let uv = Vec2 {
x: 1.0 - (0.5 + f32::atan2(d.z, d.x) / (2.0 * f32::consts::PI)),
y: 1.0 - (0.5 + f32::asin(d.y) / f32::consts::PI),
};
uvmap.insert(edge, uv);
}
mesh.add_attribute(crate::mesh::attributes::AttributeKind::UVs, uvmap);
}
pub(crate) fn cube(mesh: &mut HalfEdgeMesh, transform: Transform) {
const CUBE_NORMALS: [Vec3; 6] = [
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
Vec3 {
x: -1.0,
y: 0.0,
z: 0.0,
},
Vec3 {
x: 0.0,
y: -1.0,
z: 0.0,
},
Vec3 {
x: 1.0,
y: 0.0,
z: 0.0,
},
Vec3 {
x: 0.0,
y: 0.0,
z: 1.0,
},
Vec3 {
x: 0.0,
y: 0.0,
z: -1.0,
},
];
const CUBE_UV_BASIS: [(Vec3, Vec3); 6] = [
(
Vec3 {
x: 0.0,
y: 0.0,
z: 1.0,
},
Vec3 {
x: -1.0,
y: 0.0,
z: 0.0,
},
),
(
Vec3 {
x: 0.0,
y: 0.0,
z: 1.0,
},
Vec3 {
x: 0.0,
y: -1.0,
z: 0.0,
},
),
(
Vec3 {
x: 0.0,
y: 0.0,
z: 1.0,
},
Vec3 {
x: 1.0,
y: 0.0,
z: 0.0,
},
),
(
Vec3 {
x: 0.0,
y: 0.0,
z: -1.0,
},
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
),
(
Vec3 {
x: 1.0,
y: 0.0,
z: 0.0,
},
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
),
(
Vec3 {
x: 1.0,
y: 0.0,
z: 0.0,
},
Vec3 {
x: 0.0,
y: 1.0,
z: 0.0,
},
),
];
const UV_TRANSLATE: [Vec2; 6] = [
Vec2 { x: 0.25, y: 0.00 },
Vec2 { x: 0.25, y: 0.25 },
Vec2 { x: 0.25, y: 0.50 },
Vec2 { x: 0.25, y: 0.75 },
Vec2 { x: 0.00, y: 0.75 },
Vec2 { x: 0.50, y: 0.75 },
];
let transform = transform.compute_affine().inverse();
let mut uvmap = SecondaryMap::<HalfEdgeId, Vec2>::new();
for face in mesh.face_keys() {
let face = mesh.goto(face);
let normal = face.calculate_normal().unwrap();
let (idx, _) = CUBE_NORMALS
.iter()
.enumerate()
.max_by_key(|(_, n)| {
let n = n.dot(normal);
if n < 0.0 {
0
} else {
(1000.0 * n) as i32
}
})
.unwrap();
let (basis_u, basis_v) = CUBE_UV_BASIS[idx];
let translate = UV_TRANSLATE[idx];
for edge in face.iter_loop() {
let p = transform.transform_point(edge.position());
let uv = if true {
0.25 * Vec2 {
x: p.dot(basis_u),
y: p.dot(basis_v),
} + translate
+ Vec2 { x: 0.125, y: 0.125 }
} else {
Vec2::ZERO
};
uvmap.insert(edge.halfedge(), uv);
}
}
mesh.add_attribute(crate::mesh::attributes::AttributeKind::UVs, uvmap);
}