1use crate::gfx;
2use gfx::Buffer;
3use gfx::CmdBuf;
4
5use maths_rs::prelude::*;
6
7struct DynamicBuffer<D: gfx::Device> {
9 cpu_data: Vec<f32>,
10 gpu_data: Vec<D::Buffer>,
11 gpu_data_size: Vec<usize>,
12 vertex_count: u32
13}
14
15#[repr(C)]
17struct ImDrawVertex2d {
18 _position: [f32; 2],
19 _color: [f32; 4],
20}
21
22#[repr(C)]
24struct ImDrawVertex3d {
25 _position: [f32; 3],
26 _color: [f32; 4],
27}
28
29pub struct ImDrawInfo {
31 pub initial_buffer_size_2d: usize,
32 pub initial_buffer_size_3d: usize
33}
34
35pub struct ImDraw<D: gfx::Device> {
37 vertices_2d: DynamicBuffer<D>,
38 vertices_3d: DynamicBuffer<D>
39}
40
41impl<D> ImDraw<D> where D: gfx::Device {
43 fn new_buffer_2d_info(num_elements: usize) -> gfx::BufferInfo {
44 gfx::BufferInfo {
45 usage: gfx::BufferUsage::VERTEX,
46 cpu_access: gfx::CpuAccessFlags::WRITE,
47 format: gfx::Format::Unknown,
48 stride: std::mem::size_of::<ImDrawVertex2d>(),
49 num_elements,
50 initial_state: gfx::ResourceState::VertexConstantBuffer
51 }
52 }
53
54 fn new_buffer_3d_info(num_elements: usize) -> gfx::BufferInfo {
55 gfx::BufferInfo {
56 usage: gfx::BufferUsage::VERTEX,
57 cpu_access: gfx::CpuAccessFlags::WRITE,
58 format: gfx::Format::Unknown,
59 stride: std::mem::size_of::<ImDrawVertex3d>(),
60 num_elements,
61 initial_state: gfx::ResourceState::VertexConstantBuffer
62 }
63 }
64
65 pub fn create(info: &ImDrawInfo) -> Result<Self, super::Error> {
66 Ok(ImDraw {
67 vertices_2d: DynamicBuffer {
68 cpu_data: Vec::with_capacity(info.initial_buffer_size_2d),
69 gpu_data: Vec::new(),
70 gpu_data_size: Vec::new(),
71 vertex_count: 0
72 },
73 vertices_3d: DynamicBuffer {
74 cpu_data: Vec::with_capacity(info.initial_buffer_size_3d),
75 gpu_data: Vec::new(),
76 gpu_data_size: Vec::new(),
77 vertex_count: 0
78 },
79 })
80 }
81
82 pub fn add_vertex_2d(&mut self, v: Vec2f, col: Vec4f) {
83 for i in 0..2 {
85 self.vertices_2d.cpu_data.push(v[i])
86 }
87 for i in 0..4 {
89 self.vertices_2d.cpu_data.push(col[i])
90 }
91 }
92
93 pub fn add_line_2d(&mut self, start: Vec2f, end: Vec2f, col: Vec4f) {
94 self.add_vertex_2d(start, col);
95 self.add_vertex_2d(end, col);
96 }
97
98 pub fn add_tri_2d(&mut self, p1: Vec2f, p2: Vec2f, p3: Vec2f, col: Vec4f) {
99 self.add_vertex_2d(p1, col);
101 self.add_vertex_2d(p2, col);
102 self.add_vertex_2d(p2, col);
104 self.add_vertex_2d(p3, col);
105 self.add_vertex_2d(p3, col);
107 self.add_vertex_2d(p1, col);
108 }
109
110 pub fn add_rect_2d(&mut self, p: Vec2f, size: Vec2f, col: Vec4f) {
111 let p1 = p + Vec2f::new(size.x, 0.0);
112 let p2 = p + size;
113 let p3 = p + Vec2f::new(0.0, size.y);
114 self.add_vertex_2d(p, col);
116 self.add_vertex_2d(p1, col);
117 self.add_vertex_2d(p1, col);
119 self.add_vertex_2d(p2, col);
120 self.add_vertex_2d(p2, col);
122 self.add_vertex_2d(p3, col);
123 self.add_vertex_2d(p3, col);
125 self.add_vertex_2d(p, col);
126 }
127
128 pub fn add_vertex_3d(&mut self, v: Vec3f, col: Vec4f) {
129 for i in 0..3 {
131 self.vertices_3d.cpu_data.push(v[i])
132 }
133 for i in 0..4 {
135 self.vertices_3d.cpu_data.push(col[i])
136 }
137 }
138
139 pub fn add_line_3d(&mut self, start: Vec3f, end: Vec3f, col: Vec4f) {
140 self.add_vertex_3d(start, col);
141 self.add_vertex_3d(end, col);
142 }
143
144 pub fn add_point_3d(&mut self, pos: Vec3f, size: f32, col: Vec4f) {
145 self.add_line_3d(pos - Vec3f::unit_x() * size, pos + Vec3f::unit_x() * size, col);
146 self.add_line_3d(pos - Vec3f::unit_y() * size, pos + Vec3f::unit_y() * size, col);
147 self.add_line_3d(pos - Vec3f::unit_z() * size, pos + Vec3f::unit_z() * size, col);
148 }
149
150 pub fn add_circle_3d_xz(&mut self, pos: Vec3f, radius: f32, col: Vec4f) {
151 let segs = 16;
152 let step = (f32::pi() * 2.0) / segs as f32;
153 for i in 0..16 {
154 let ix = i as f32 * step;
155 let iy = (i + 1) as f32 * step;
156 self.add_line_3d(pos + Vec3f::new(f32::sin(ix), 0.0, f32::cos(ix)) * radius,
157 pos + Vec3f::new(f32::sin(iy), 0.0, f32::cos(iy)) * radius, col);
158 }
159 }
160
161 pub fn add_aabb_3d(&mut self, aabb_min: Vec3f, aabb_max: Vec3f, col: Vec4f) {
163 self.add_line_3d(vec3f(aabb_min.x, aabb_min.y, aabb_min.z), vec3f(aabb_max.x, aabb_min.y, aabb_min.z), col);
164 self.add_line_3d(vec3f(aabb_min.x, aabb_min.y, aabb_min.z), vec3f(aabb_min.x, aabb_min.y, aabb_max.z), col);
165 self.add_line_3d(vec3f(aabb_min.x, aabb_min.y, aabb_max.z), vec3f(aabb_max.x, aabb_min.y, aabb_max.z), col);
166 self.add_line_3d(vec3f(aabb_max.x, aabb_min.y, aabb_max.z), vec3f(aabb_max.x, aabb_min.y, aabb_min.z), col);
167 self.add_line_3d(vec3f(aabb_min.x, aabb_max.y, aabb_min.z), vec3f(aabb_max.x, aabb_max.y, aabb_min.z), col);
168 self.add_line_3d(vec3f(aabb_min.x, aabb_max.y, aabb_min.z), vec3f(aabb_min.x, aabb_max.y, aabb_max.z), col);
169 self.add_line_3d(vec3f(aabb_min.x, aabb_max.y, aabb_max.z), vec3f(aabb_max.x, aabb_max.y, aabb_max.z), col);
170 self.add_line_3d(vec3f(aabb_max.x, aabb_max.y, aabb_max.z), vec3f(aabb_max.x, aabb_max.y, aabb_min.z), col);
171 self.add_line_3d(vec3f(aabb_min.x, aabb_min.y, aabb_min.z), vec3f(aabb_min.x, aabb_max.y, aabb_min.z), col);
172 self.add_line_3d(vec3f(aabb_max.x, aabb_min.y, aabb_min.z), vec3f(aabb_max.x, aabb_max.y, aabb_min.z), col);
173 self.add_line_3d(vec3f(aabb_max.x, aabb_min.y, aabb_max.z), vec3f(aabb_max.x, aabb_max.y, aabb_max.z), col);
174 self.add_line_3d(vec3f(aabb_min.x, aabb_min.y, aabb_max.z), vec3f(aabb_min.x, aabb_max.y, aabb_max.z), col);
175 }
176
177 pub fn add_obb_3d(&mut self, obb: Vec<Vec3f>, col: Vec4f) {
179 self.add_line_3d(vec3f(obb[0].x, obb[0].y, obb[0].z), vec3f(obb[1].x, obb[1].y, obb[1].z), col);
180 self.add_line_3d(vec3f(obb[1].x, obb[1].y, obb[1].z), vec3f(obb[2].x, obb[2].y, obb[2].z), col);
181 self.add_line_3d(vec3f(obb[2].x, obb[2].y, obb[2].z), vec3f(obb[3].x, obb[3].y, obb[3].z), col);
182 self.add_line_3d(vec3f(obb[3].x, obb[3].y, obb[3].z), vec3f(obb[0].x, obb[0].y, obb[0].z), col);
183 self.add_line_3d(vec3f(obb[4].x, obb[4].y, obb[4].z), vec3f(obb[5].x, obb[5].y, obb[5].z), col);
184 self.add_line_3d(vec3f(obb[5].x, obb[5].y, obb[5].z), vec3f(obb[6].x, obb[6].y, obb[6].z), col);
185 self.add_line_3d(vec3f(obb[6].x, obb[6].y, obb[6].z), vec3f(obb[7].x, obb[7].y, obb[7].z), col);
186 self.add_line_3d(vec3f(obb[7].x, obb[7].y, obb[7].z), vec3f(obb[4].x, obb[4].y, obb[4].z), col);
187 self.add_line_3d(vec3f(obb[4].x, obb[4].y, obb[4].z), vec3f(obb[0].x, obb[0].y, obb[0].z), col);
188 self.add_line_3d(vec3f(obb[5].x, obb[5].y, obb[5].z), vec3f(obb[1].x, obb[1].y, obb[1].z), col);
189 self.add_line_3d(vec3f(obb[6].x, obb[6].y, obb[6].z), vec3f(obb[2].x, obb[2].y, obb[2].z), col);
190 self.add_line_3d(vec3f(obb[7].x, obb[7].y, obb[7].z), vec3f(obb[3].x, obb[3].y, obb[3].z), col);
191 }
192
193 pub fn add_frustum(&mut self, view_proj: Mat4f, col: Vec4f) {
194 let corners = view_proj.get_frustum_corners();
195 let mut obb = Vec::new();
196 for c in corners {
197 obb.push(c);
198 }
199
200 self.add_line_3d(obb[0], obb[1], col);
201 self.add_line_3d(obb[1], obb[3], col);
202 self.add_line_3d(obb[3], obb[2], col);
203 self.add_line_3d(obb[2], obb[0], col);
204
205 self.add_line_3d(obb[4], obb[5], col);
206 self.add_line_3d(obb[5], obb[7], col);
207 self.add_line_3d(obb[7], obb[6], col);
208 self.add_line_3d(obb[6], obb[4], col);
209
210 self.add_line_3d(obb[0], obb[4], col);
211 self.add_line_3d(obb[1], obb[5], col);
212 self.add_line_3d(obb[2], obb[6], col);
213 self.add_line_3d(obb[3], obb[7], col);
214 }
215
216 pub fn submit(&mut self, device: &mut D, buffer_index: usize) -> Result<(), super::Error> {
217 if !self.vertices_2d.cpu_data.is_empty() {
218 let num_elems = self.vertices_2d.cpu_data.len() / 6;
219 while buffer_index >= self.vertices_2d.gpu_data.len() {
220 self.vertices_2d.gpu_data.push(
222 device.create_buffer::<u8>(&Self::new_buffer_2d_info(num_elems), None)?
223 );
224 self.vertices_2d.gpu_data_size.push(num_elems);
225 }
226 if num_elems > self.vertices_2d.gpu_data_size[buffer_index] {
227 self.vertices_2d.gpu_data[buffer_index] = device.create_buffer::<u8>(
229 &Self::new_buffer_2d_info(num_elems), None)?;
230 }
231 self.vertices_2d.gpu_data[buffer_index].update(0, self.vertices_2d.cpu_data.as_slice())?;
233 self.vertices_2d.gpu_data_size[buffer_index] = num_elems;
234 self.vertices_2d.vertex_count = num_elems as u32;
235 self.vertices_2d.cpu_data.clear();
236 }
237 if !self.vertices_3d.cpu_data.is_empty() {
238 let num_elems = self.vertices_3d.cpu_data.len() / 7;
239 while buffer_index >= self.vertices_3d.gpu_data.len() {
240 self.vertices_3d.gpu_data.push(
242 device.create_buffer::<u8>(&Self::new_buffer_3d_info(num_elems), None)?
243 );
244 self.vertices_3d.gpu_data_size.push(num_elems);
245 }
246 if num_elems > self.vertices_3d.gpu_data_size[buffer_index] {
247 self.vertices_3d.gpu_data[buffer_index] = device.create_buffer::<u8>(
249 &Self::new_buffer_3d_info(num_elems), None)?;
250 }
251 self.vertices_3d.gpu_data[buffer_index].update(0, self.vertices_3d.cpu_data.as_slice())?;
253 self.vertices_3d.gpu_data_size[buffer_index] = num_elems;
254 self.vertices_3d.vertex_count = num_elems as u32;
255 self.vertices_3d.cpu_data.clear();
256 }
257 Ok(())
258 }
259
260 pub fn draw_2d(&mut self, cmd: &D::CmdBuf, buffer_index: usize) {
261 if buffer_index < self.vertices_2d.gpu_data.len() {
262 cmd.set_vertex_buffer(&self.vertices_2d.gpu_data[buffer_index], 0);
263 cmd.draw_instanced(self.vertices_2d.vertex_count, 1, 0, 0);
264 }
265 }
266
267 pub fn draw_3d(&mut self, cmd: &D::CmdBuf, buffer_index: usize) {
268 if buffer_index < self.vertices_3d.gpu_data.len() {
269 cmd.set_vertex_buffer(&self.vertices_3d.gpu_data[buffer_index], 0);
270 cmd.draw_instanced(self.vertices_3d.vertex_count, 1, 0, 0);
271 }
272 }
273}