bounding_sphere3d/
utils3d.rs

1use core::f32::consts::{FRAC_PI_2, FRAC_PI_4, FRAC_PI_6};
2use std::sync::Arc;
3
4use kiss3d::prelude::*;
5use kiss3d::procedural::{IndexBuffer, RenderMesh};
6
7#[allow(dead_code)]
8fn main() {
9    println!(
10        "This module contains helper functions to use kiss3d,
11    isolated from the rest of the examples for the sake of simplicity."
12    );
13}
14
15/// Converts a hue (from 0..=1) to rgb
16#[allow(dead_code)]
17pub fn hue_to_rgb(h: f32) -> (f32, f32, f32) {
18    let kr = (5.0 + h * 6.0).rem_euclid(6.0);
19    let kg = (3.0 + h * 6.0).rem_euclid(6.0);
20    let kb = (1.0 + h * 6.0).rem_euclid(6.0);
21
22    let r = 1.0 - kr.min(4.0 - kr).clamp(0.0, 1.0);
23    let g = 1.0 - kg.min(4.0 - kg).clamp(0.0, 1.0);
24    let b = 1.0 - kb.min(4.0 - kb).clamp(0.0, 1.0);
25
26    (r, g, b)
27}
28
29/// Returns [lissajous curve](https://en.wikipedia.org/wiki/Lissajous_curve) coordinates for time `t`.
30///
31/// This uses hardcoded parameters to have an arbitrary pleasing trajectory.
32#[allow(dead_code)]
33pub fn lissajous_3d(t: f32) -> Vec3 {
34    // Some hardcoded parameters to have a pleasing lissajous trajectory.
35    lissajous_3d_with_params(t, 3.0, 2.0, 1.0, FRAC_PI_2, FRAC_PI_4, FRAC_PI_6)
36}
37
38/// Returns [lissajous curve](https://en.wikipedia.org/wiki/Lissajous_curve) coordinates.
39#[allow(dead_code)]
40pub fn lissajous_3d_with_params(
41    t: f32,
42    a: f32,
43    b: f32,
44    c: f32,
45    delta_x: f32,
46    delta_y: f32,
47    delta_z: f32,
48) -> Vec3 {
49    let x = (a * t + delta_x).sin();
50    let y = (b * t + delta_y).sin();
51    let z = (c * t + delta_z).sin();
52    Vec3::new(x, y, z) * 0.75f32
53}
54
55/// Uses [`kiss3d`] to display the line passed as parameter.
56#[allow(dead_code)]
57pub fn draw_polyline(window: &mut Window, polyline: Vec<(Vec3, Vec3)>, color: Color) {
58    for line in polyline {
59        let a = line.0;
60        let b = line.1;
61        window.draw_line(a, b, color, 2.0, false);
62    }
63}
64
65/// Draws a text in the top left corner of the screen.
66///
67/// This uses a hardcoded position, size, color.
68#[allow(dead_code)]
69pub fn draw_text(window: &mut Window, font: &Arc<Font>, text: &str) {
70    window.draw_text(text, Vec2::new(10.0, 66.0), 30.0, font, WHITE);
71}
72
73/// Creates a GpuMesh3d from parry3d's trimesh vertices and indices.
74#[allow(dead_code)]
75pub fn create_mesh_from_trimesh(
76    vertices: Vec<Vec3>,
77    indices: Vec<[u32; 3]>,
78) -> std::rc::Rc<std::cell::RefCell<kiss3d::resource::GpuMesh3d>> {
79    use std::cell::RefCell;
80    use std::rc::Rc;
81
82    let mut render_mesh =
83        RenderMesh::new(vertices, None, None, Some(IndexBuffer::Unified(indices)));
84    render_mesh.replicate_vertices();
85    render_mesh.recompute_normals();
86    Rc::new(RefCell::new(render_mesh.into()))
87}
88
89/// Draws a 3D AABB (axis-aligned bounding box) as a wireframe.
90#[allow(dead_code)]
91pub fn draw_aabb3(window: &mut Window, mins: Vec3, maxs: Vec3, color: Color) {
92    // Bottom face
93    window.draw_line(
94        Vec3::new(mins.x, mins.y, mins.z),
95        Vec3::new(maxs.x, mins.y, mins.z),
96        color,
97        2.0,
98        false,
99    );
100    window.draw_line(
101        Vec3::new(maxs.x, mins.y, mins.z),
102        Vec3::new(maxs.x, mins.y, maxs.z),
103        color,
104        2.0,
105        false,
106    );
107    window.draw_line(
108        Vec3::new(maxs.x, mins.y, maxs.z),
109        Vec3::new(mins.x, mins.y, maxs.z),
110        color,
111        2.0,
112        false,
113    );
114    window.draw_line(
115        Vec3::new(mins.x, mins.y, maxs.z),
116        Vec3::new(mins.x, mins.y, mins.z),
117        color,
118        2.0,
119        false,
120    );
121    // Top face
122    window.draw_line(
123        Vec3::new(mins.x, maxs.y, mins.z),
124        Vec3::new(maxs.x, maxs.y, mins.z),
125        color,
126        2.0,
127        false,
128    );
129    window.draw_line(
130        Vec3::new(maxs.x, maxs.y, mins.z),
131        Vec3::new(maxs.x, maxs.y, maxs.z),
132        color,
133        2.0,
134        false,
135    );
136    window.draw_line(
137        Vec3::new(maxs.x, maxs.y, maxs.z),
138        Vec3::new(mins.x, maxs.y, maxs.z),
139        color,
140        2.0,
141        false,
142    );
143    window.draw_line(
144        Vec3::new(mins.x, maxs.y, maxs.z),
145        Vec3::new(mins.x, maxs.y, mins.z),
146        color,
147        2.0,
148        false,
149    );
150    // Vertical edges
151    window.draw_line(
152        Vec3::new(mins.x, mins.y, mins.z),
153        Vec3::new(mins.x, maxs.y, mins.z),
154        color,
155        2.0,
156        false,
157    );
158    window.draw_line(
159        Vec3::new(maxs.x, mins.y, mins.z),
160        Vec3::new(maxs.x, maxs.y, mins.z),
161        color,
162        2.0,
163        false,
164    );
165    window.draw_line(
166        Vec3::new(maxs.x, mins.y, maxs.z),
167        Vec3::new(maxs.x, maxs.y, maxs.z),
168        color,
169        2.0,
170        false,
171    );
172    window.draw_line(
173        Vec3::new(mins.x, mins.y, maxs.z),
174        Vec3::new(mins.x, maxs.y, maxs.z),
175        color,
176        2.0,
177        false,
178    );
179}
180
181/// Draws a sphere wireframe using 3 orthogonal circles.
182#[allow(dead_code)]
183pub fn draw_sphere_wires(window: &mut Window, center: Vec3, radius: f32, color: Color) {
184    let segments = 32;
185    let tau = std::f32::consts::TAU;
186
187    for i in 0..segments {
188        let angle1 = (i as f32 / segments as f32) * tau;
189        let angle2 = ((i + 1) as f32 / segments as f32) * tau;
190
191        // XY plane circle
192        let p1 = center + Vec3::new(radius * angle1.cos(), radius * angle1.sin(), 0.0);
193        let p2 = center + Vec3::new(radius * angle2.cos(), radius * angle2.sin(), 0.0);
194        window.draw_line(p1, p2, color, 2.0, false);
195
196        // XZ plane circle
197        let p1 = center + Vec3::new(radius * angle1.cos(), 0.0, radius * angle1.sin());
198        let p2 = center + Vec3::new(radius * angle2.cos(), 0.0, radius * angle2.sin());
199        window.draw_line(p1, p2, color, 2.0, false);
200
201        // YZ plane circle
202        let p1 = center + Vec3::new(0.0, radius * angle1.cos(), radius * angle1.sin());
203        let p2 = center + Vec3::new(0.0, radius * angle2.cos(), radius * angle2.sin());
204        window.draw_line(p1, p2, color, 2.0, false);
205    }
206}