ncollide3d/procedural/path/
arrowhead_cap.rs1use crate::procedural::path::PolylineCompatibleCap;
2use crate::procedural::utils;
3use na::{self, Isometry3, Point3, Vector3};
4use simba::scalar::RealField;
5
6pub struct ArrowheadCap<N> {
8 radius_scale: N,
9 front_dist_to_head: N,
10 back_dist_to_head: N,
11}
12
13impl<N: RealField + Copy> ArrowheadCap<N> {
14 pub fn new(radius_scale: N, front_dist_to_head: N, back_dist_to_head: N) -> ArrowheadCap<N> {
21 ArrowheadCap {
22 radius_scale: radius_scale,
23 front_dist_to_head: front_dist_to_head,
24 back_dist_to_head: back_dist_to_head,
25 }
26 }
27
28 fn do_gen_cap(
29 &self,
30 attach_id: u32,
31 pattern: &[Point3<N>],
32 pt: &Point3<N>,
33 dir: &Vector3<N>,
34 closed: bool,
35 negative_shifts: bool,
36 coords: &mut Vec<Point3<N>>,
37 indices: &mut Vec<Point3<u32>>,
38 ) {
39 let front_dist_to_head = if negative_shifts {
40 -self.front_dist_to_head
41 } else {
42 self.front_dist_to_head
43 };
44 let back_dist_to_head = if negative_shifts {
45 -self.back_dist_to_head
46 } else {
47 self.back_dist_to_head
48 };
49 let pointy_thing = *pt + *dir * front_dist_to_head;
50 let start_id = coords.len() as u32;
51 let npts = pattern.len() as u32;
52 let mut attach_id = attach_id;
53
54 if !(self.radius_scale == na::convert(1.0)) || !back_dist_to_head.is_zero() {
55 let mut new_pattern: Vec<Point3<N>> =
56 pattern.iter().map(|p| p * self.radius_scale).collect();
57
58 let transform;
61 let back_shift = *dir * back_dist_to_head;
62
63 if dir.x.is_zero() && dir.z.is_zero() {
64 transform =
66 Isometry3::face_towards(&(*pt - back_shift), &(*pt + *dir), &Vector3::x());
67 } else {
68 transform =
69 Isometry3::face_towards(&(*pt - back_shift), &(*pt + *dir), &Vector3::y());
70 }
71
72 for p in &mut new_pattern {
73 *p = transform * &*p
74 }
75
76 coords.extend(new_pattern.into_iter());
77
78 if closed {
79 utils::push_ring_indices(attach_id, start_id, npts, indices)
80 } else {
81 utils::push_open_ring_indices(attach_id, start_id, npts, indices)
82 }
83
84 attach_id = start_id;
85 }
86
87 if closed {
88 utils::push_degenerate_top_ring_indices(attach_id, coords.len() as u32, npts, indices);
89 } else {
90 utils::push_degenerate_open_top_ring_indices(
91 attach_id,
92 coords.len() as u32,
93 npts,
94 indices,
95 );
96 }
97
98 coords.push(pointy_thing);
99 }
100}
101
102impl<N: RealField + Copy> PolylineCompatibleCap<N> for ArrowheadCap<N> {
103 fn gen_end_cap(
104 &self,
105 attach_id: u32,
106 pattern: &[Point3<N>],
107 pt: &Point3<N>,
108 dir: &Vector3<N>,
109 closed: bool,
110 coords: &mut Vec<Point3<N>>,
111 indices: &mut Vec<Point3<u32>>,
112 ) {
113 let start_indices_id = indices.len();
114
115 self.do_gen_cap(attach_id, pattern, pt, dir, closed, false, coords, indices);
116 utils::reverse_clockwising(&mut indices[start_indices_id..])
117 }
118
119 fn gen_start_cap(
120 &self,
121 attach_id: u32,
122 pattern: &[Point3<N>],
123 pt: &Point3<N>,
124 dir: &Vector3<N>,
125 closed: bool,
126 coords: &mut Vec<Point3<N>>,
127 indices: &mut Vec<Point3<u32>>,
128 ) {
129 self.do_gen_cap(attach_id, pattern, pt, dir, closed, true, coords, indices)
130 }
131}