1
- use std:: { f32:: consts:: TAU , mem } ;
1
+ use std:: { f32:: consts:: TAU , iter } ;
2
2
3
3
use bevy_asset:: Handle ;
4
4
use bevy_ecs:: system:: Resource ;
@@ -9,22 +9,28 @@ use bevy_render::prelude::{Color, Mesh};
9
9
/// Useful for visual debugging.
10
10
#[ derive( Resource ) ]
11
11
pub struct DebugDraw {
12
- positions : Vec < [ f32 ; 3 ] > ,
13
- colors : Vec < [ f32 ; 4 ] > ,
14
- pub ( crate ) mesh_handle : Option < Handle < Mesh > > ,
12
+ pub ( crate ) list_mesh_handle : Option < Handle < Mesh > > ,
13
+ pub ( crate ) list_positions : Vec < [ f32 ; 3 ] > ,
14
+ pub ( crate ) list_colors : Vec < [ f32 ; 4 ] > ,
15
+ pub ( crate ) strip_mesh_handle : Option < Handle < Mesh > > ,
16
+ pub ( crate ) strip_positions : Vec < [ f32 ; 3 ] > ,
17
+ pub ( crate ) strip_colors : Vec < [ f32 ; 4 ] > ,
15
18
/// The amount of line segments to use when drawing a circle.
16
19
///
17
- /// Defaults to `24 `.
20
+ /// Defaults to `32 `.
18
21
pub circle_segments : u32 ,
19
22
}
20
23
21
24
impl Default for DebugDraw {
22
25
fn default ( ) -> Self {
23
26
DebugDraw {
24
- positions : Vec :: new ( ) ,
25
- colors : Vec :: new ( ) ,
26
- mesh_handle : None ,
27
- circle_segments : 24 ,
27
+ list_mesh_handle : None ,
28
+ list_positions : Vec :: new ( ) ,
29
+ list_colors : Vec :: new ( ) ,
30
+ strip_mesh_handle : None ,
31
+ strip_positions : Vec :: new ( ) ,
32
+ strip_colors : Vec :: new ( ) ,
33
+ circle_segments : 32 ,
28
34
}
29
35
}
30
36
}
@@ -39,8 +45,9 @@ impl DebugDraw {
39
45
/// Draw a line from `start` to `end`.
40
46
#[ inline]
41
47
pub fn line_gradient ( & mut self , start : Vec3 , end : Vec3 , start_color : Color , end_color : Color ) {
42
- self . positions . extend ( [ start. to_array ( ) , end. to_array ( ) ] ) ;
43
- self . colors . extend ( [
48
+ self . list_positions
49
+ . extend ( [ start. to_array ( ) , end. to_array ( ) ] ) ;
50
+ self . list_colors . extend ( [
44
51
start_color. as_linear_rgba_f32 ( ) ,
45
52
end_color. as_linear_rgba_f32 ( ) ,
46
53
] ) ;
@@ -49,7 +56,7 @@ impl DebugDraw {
49
56
/// Draw a line from `start` to `start + vector`.
50
57
#[ inline]
51
58
pub fn ray ( & mut self , start : Vec3 , vector : Vec3 , color : Color ) {
52
- self . ray_gradient ( start, vector , color , color) ;
59
+ self . line ( start, start + vector , color) ;
53
60
}
54
61
55
62
/// Draw a line from `start` to `start + vector`.
@@ -68,25 +75,23 @@ impl DebugDraw {
68
75
#[ inline]
69
76
pub fn circle ( & mut self , position : Vec3 , normal : Vec3 , radius : f32 , color : Color ) {
70
77
let rotation = Quat :: from_rotation_arc ( Vec3 :: Z , normal) ;
71
- self . positions
72
- . extend ( ( 0 ..self . circle_segments ) . into_iter ( ) . flat_map ( |i| {
73
- let mut angle = i as f32 * TAU / self . circle_segments as f32 ;
74
- let start = rotation * ( Vec2 :: from ( angle. sin_cos ( ) ) * radius) . extend ( 0. ) + position;
75
78
76
- angle += TAU / self . circle_segments as f32 ;
77
- let end = rotation * ( Vec2 :: from ( angle. sin_cos ( ) ) * radius) . extend ( 0. ) + position;
79
+ let positions = self
80
+ . circle_inner ( radius)
81
+ . map ( |vec2| ( rotation * vec2. extend ( 0. ) + position) . to_array ( ) )
82
+ . chain ( iter:: once ( Vec3 :: NAN . to_array ( ) ) ) ;
78
83
79
- [ start. to_array ( ) , end. to_array ( ) ]
80
- } ) ) ;
81
-
82
- self . colors . extend (
83
- std:: iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( self . circle_segments as usize * 2 ) ,
84
- ) ;
84
+ self . strip_positions . extend ( positions) ;
85
+ self . add_strip_color ( color, ( self . circle_segments + 1 ) as usize ) ;
85
86
}
86
87
87
88
/// Draw a sphere.
88
89
#[ inline]
89
90
pub fn sphere ( & mut self , position : Vec3 , radius : f32 , color : Color ) {
91
+ self . strip_colors
92
+ . reserve ( ( self . circle_segments + 1 ) as usize * 3 ) ;
93
+ self . strip_positions
94
+ . reserve ( ( self . circle_segments + 1 ) as usize * 3 ) ;
90
95
self . circle ( position, Vec3 :: X , radius, color) ;
91
96
self . circle ( position, Vec3 :: Y , radius, color) ;
92
97
self . circle ( position, Vec3 :: Z , radius, color) ;
@@ -100,9 +105,10 @@ impl DebugDraw {
100
105
let tr = ( position + rotation * vec3 ( half_size. x , half_size. y , 0. ) ) . to_array ( ) ;
101
106
let bl = ( position + rotation * vec3 ( -half_size. x , -half_size. y , 0. ) ) . to_array ( ) ;
102
107
let br = ( position + rotation * vec3 ( half_size. x , -half_size. y , 0. ) ) . to_array ( ) ;
103
- self . positions . extend ( [ tl, tr, tr, br, br, bl, bl, tl] ) ;
104
- self . colors
105
- . extend ( std:: iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( 8 ) ) ;
108
+
109
+ self . strip_positions
110
+ . extend ( [ tl, tr, br, bl, tl, [ f32:: NAN ; 3 ] ] ) ;
111
+ self . add_strip_color ( color, 5 ) ;
106
112
}
107
113
108
114
/// Draw a box.
@@ -119,19 +125,19 @@ impl DebugDraw {
119
125
let trb = ( position + rotation * vec3 ( half_size. x , half_size. y , -half_size. z ) ) . to_array ( ) ;
120
126
let blb = ( position + rotation * vec3 ( -half_size. x , -half_size. y , -half_size. z ) ) . to_array ( ) ;
121
127
let brb = ( position + rotation * vec3 ( half_size. x , -half_size. y , -half_size. z ) ) . to_array ( ) ;
122
- self . positions . extend ( [
128
+
129
+ self . list_positions . extend ( [
123
130
tlf, trf, trf, brf, brf, blf, blf, tlf, // Front
124
131
tlb, trb, trb, brb, brb, blb, blb, tlb, // Back
125
132
tlf, tlb, trf, trb, brf, brb, blf, blb, // Front to back
126
133
] ) ;
127
- self . colors
128
- . extend ( std:: iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( 24 ) ) ;
134
+ self . add_list_color ( color, 24 ) ;
129
135
}
130
136
131
137
/// Draw a line from `start` to `end`.
132
138
#[ inline]
133
139
pub fn line_2d ( & mut self , start : Vec2 , end : Vec2 , color : Color ) {
134
- self . line_gradient_2d ( start, end, color , color) ;
140
+ self . line ( start. extend ( 0. ) , end. extend ( 0. ) , color) ;
135
141
}
136
142
137
143
/// Draw a line from `start` to `end`.
@@ -149,7 +155,7 @@ impl DebugDraw {
149
155
/// Draw a line from `start` to `start + vector`.
150
156
#[ inline]
151
157
pub fn ray_2d ( & mut self , start : Vec2 , vector : Vec2 , color : Color ) {
152
- self . ray_gradient_2d ( start, vector , color , color) ;
158
+ self . line_2d ( start, start + vector , color) ;
153
159
}
154
160
155
161
/// Draw a line from `start` to `start + vector`.
@@ -167,7 +173,13 @@ impl DebugDraw {
167
173
// Draw a circle.
168
174
#[ inline]
169
175
pub fn circle_2d ( & mut self , position : Vec2 , radius : f32 , color : Color ) {
170
- self . circle ( position. extend ( 0. ) , Vec3 :: Z , radius, color) ;
176
+ let positions = self
177
+ . circle_inner ( radius)
178
+ . map ( |vec2| ( vec2 + position) . extend ( 0. ) . to_array ( ) )
179
+ . chain ( iter:: once ( [ f32:: NAN ; 3 ] ) ) ;
180
+
181
+ self . strip_positions . extend ( positions) ;
182
+ self . add_strip_color ( color, ( self . circle_segments + 1 ) as usize ) ;
171
183
}
172
184
173
185
/// Draw a rectangle.
@@ -181,17 +193,35 @@ impl DebugDraw {
181
193
) ;
182
194
}
183
195
184
- /// Clear everything drawn up to this point, this frame.
185
196
#[ inline]
186
- pub fn clear ( & mut self ) {
187
- self . positions . clear ( ) ;
188
- self . colors . clear ( ) ;
197
+ fn add_strip_color ( & mut self , color : Color , amount : usize ) {
198
+ self . strip_colors . extend (
199
+ iter:: repeat ( color. as_linear_rgba_f32 ( ) )
200
+ . take ( amount)
201
+ . chain ( iter:: once ( [ f32:: NAN ; 4 ] ) ) ,
202
+ ) ;
189
203
}
190
204
191
- /// Take the positions and colors data from `self` and overwrite the `mesh`'s vertex positions and colors.
192
205
#[ inline]
193
- pub ( crate ) fn update_mesh ( & mut self , mesh : & mut Mesh ) {
194
- mesh. insert_attribute ( Mesh :: ATTRIBUTE_POSITION , mem:: take ( & mut self . positions ) ) ;
195
- mesh. insert_attribute ( Mesh :: ATTRIBUTE_COLOR , mem:: take ( & mut self . colors ) ) ;
206
+ fn add_list_color ( & mut self , color : Color , amount : usize ) {
207
+ self . list_colors
208
+ . extend ( iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( amount) ) ;
209
+ }
210
+
211
+ fn circle_inner ( & self , radius : f32 ) -> impl Iterator < Item = Vec2 > {
212
+ let circle_segments = self . circle_segments ;
213
+ ( 0 ..( circle_segments + 1 ) ) . into_iter ( ) . map ( move |i| {
214
+ let angle = i as f32 * TAU / circle_segments as f32 ;
215
+ Vec2 :: from ( angle. sin_cos ( ) ) * radius
216
+ } )
217
+ }
218
+
219
+ /// Clear everything drawn up to this point, this frame.
220
+ #[ inline]
221
+ pub fn clear ( & mut self ) {
222
+ self . list_positions . clear ( ) ;
223
+ self . list_colors . clear ( ) ;
224
+ self . strip_positions . clear ( ) ;
225
+ self . strip_colors . clear ( ) ;
196
226
}
197
227
}
0 commit comments