1use std::f32::consts;
7use std::error::Error;
8use image;
9use bytemuck;
10use glam;
11use wgpu;
12
13#[repr(C)]
15#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
16pub struct Vertex {
17 pub pos: [f32; 4],
19 pub norm: [f32; 4],
21 pub col: [u32; 4],
23 pub tex_coord: [f32; 2],
25 pub ix: u32
27}
28
29pub fn vtx(pos: [i8; 3], tc: [i8; 2]) -> Vertex {
31 Vertex{
32 pos: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
33 norm: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
34 col: (0..4).map(|i| if i < 3 { (pos[i] + 2) as u32 * 255 / 4 } else { 255 }
35 ).collect::<Vec<_>>().try_into().unwrap(),
36 tex_coord: [tc[0] as f32, tc[1] as f32],
37 ix: 0
38 }
39}
40
41pub fn vtf(pos: [i8; 3], tc: [f32; 2]) -> Vertex {
43 Vertex{
44 pos: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
45 norm: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
46 col: (0..4).map(|i| if i < 3 { (pos[i] + 2) as u32 * 255 / 4 } else { 255 }
47 ).collect::<Vec<_>>().try_into().unwrap(),
48 tex_coord: tc,
49 ix: 0
50 }
51}
52
53#[derive(Debug)]
55pub struct FaceInf {
56 pub nfaces: u64,
58 pub il: Vec<u64>,
60 pub tf: fn ((usize, usize, usize)) -> usize
62}
63
64#[derive(Debug)]
66pub struct VIP {
67 pub vs: wgpu::Buffer,
69 pub is: wgpu::Buffer,
71 pub p: FaceInf
73}
74
75pub fn locscale(o: &[f32; 3], scale: f32, vi: (Vec<Vertex>, Vec<u16>, FaceInf))
77 -> (Vec<Vertex>, Vec<u16>, FaceInf) {
78 (
79 vi.0.into_iter().enumerate().map(
80 |(j, Vertex{pos: p, col: c, norm: n, tex_coord: tc, ix: _})| {
81 Vertex{
82 pos: p.iter().enumerate().map(|(i, &v)| {
83 if i < 3 { o[i] + v * scale } else { v } }).collect::<Vec<_>>().try_into().unwrap(),
85 col: c,
86 norm: n,
87 tex_coord: tc,
88 ix: j as u32
89 }
90 }).collect(),
91 vi.1,
92 vi.2
93 )
94}
95
96pub fn create_vertices_cube_6_textures(
98 tf: fn ((usize, usize, usize)) -> usize)
99 -> (Vec<Vertex>, Vec<u16>, FaceInf) {
100 let vertex_data = [ vtx([1, -1, 1], [0, 1]),
103 vtx([1, -1, -1], [1, 1]),
104 vtx([1, 1, -1], [1, 0]),
105 vtx([1, 1, 1], [0, 0]),
106 vtx([-1, -1, 1], [0, 1]),
108 vtx([-1, 1, 1], [1, 1]),
109 vtx([-1, 1, -1], [1, 0]),
110 vtx([-1, -1, -1], [0, 0]),
111 vtx([1, 1, -1], [0, 1]),
113 vtx([-1, 1, -1], [1, 1]),
114 vtx([-1, 1, 1], [1, 0]),
115 vtx([1, 1, 1], [0, 0]),
116 vtx([1, -1, -1], [0, 1]),
118 vtx([1, -1, 1], [1, 1]),
119 vtx([-1, -1, 1], [1, 0]),
120 vtx([-1, -1, -1], [0, 0]),
121 vtx([-1, 1, 1], [0, 1]),
123 vtx([-1, -1, 1], [1, 1]),
124 vtx([1, -1, 1], [1, 0]),
125 vtx([1, 1, 1], [0, 0]),
126
127#[cfg(interrupt_vertex)] vtx([0, 2, 0], [0, 1]),
129#[cfg(interrupt_vertex)] vtx([2, 2, 0], [1, 1]),
130#[cfg(interrupt_vertex)] vtx([2, 0, 0], [1, 0]),
131#[cfg(interrupt_vertex)] vtx([0, 0, 0], [0, 0]),
132
133 vtx([-1, 1, -1], [0, 1]),
135 vtx([1, 1, -1], [1, 1]),
136 vtx([1, -1, -1], [1, 0]),
137 vtx([-1, -1, -1], [0, 0])
138 ];
139
140 let index_data: &[u16] = &[
141 0, 1, 3, 2, 3, 1, 4, 5, 7, 6, 7, 5, 8, 9, 11, 10, 11, 9, 12, 13, 15, 14, 15, 13, 16, 17, 19, 18, 19, 17, #[cfg(interrupt_vertex)] 24,
149#[cfg(interrupt_vertex)] 25,
150#[cfg(interrupt_vertex)] 27,
151#[cfg(interrupt_vertex)] 26,
152#[cfg(interrupt_vertex)] 27,
153#[cfg(interrupt_vertex)] 25,
154
155 20, 21, 23, 22, 23, 21 ];
157
158 let nfaces = index_data.len() as u64 / 6;
159 (vertex_data.to_vec(), index_data.to_vec(), FaceInf{
160 nfaces,
161 il: (0..=nfaces).map(|i| i * 6).collect(),
162 tf: tf}) }
164
165pub fn create_vertices_cube_expansion_plan(
167 tf: fn ((usize, usize, usize)) -> usize)
168 -> (Vec<Vertex>, Vec<u16>, FaceInf) {
169 let vertex_data = [ vtf([1, -1, 1], [0.25, 0.0]),
172 vtf([1, -1, -1], [0.25, 0.25]),
173 vtf([1, 1, -1], [0.5, 0.25]),
174 vtf([1, 1, 1], [0.5, 0.0]),
175 vtf([-1, -1, 1], [0.25, 0.75]),
177 vtf([-1, 1, 1], [0.5, 0.75]),
178 vtf([-1, 1, -1], [0.5, 0.5]),
179 vtf([-1, -1, -1], [0.25, 0.5]),
180 vtf([1, 1, -1], [0.5, 0.25]),
182 vtf([-1, 1, -1], [0.75, 0.25]),
183 vtf([-1, 1, 1], [0.75, 0.0]),
184 vtf([1, 1, 1], [0.5, 0.0]),
185 vtf([1, -1, -1], [0.0, 0.5]),
187 vtf([1, -1, 1], [0.0, 0.75]),
188 vtf([-1, -1, 1], [0.25, 0.75]),
189 vtf([-1, -1, -1], [0.25, 0.5]),
190 vtf([-1, 1, 1], [0.5, 0.75]),
192 vtf([-1, -1, 1], [0.25, 0.75]),
193 vtf([1, -1, 1], [0.25, 1.0]),
194 vtf([1, 1, 1], [0.5, 1.0]),
195 vtf([-1, 1, -1], [0.5, 0.5]),
197 vtf([1, 1, -1], [0.5, 0.25]),
198 vtf([1, -1, -1], [0.25, 0.25]),
199 vtf([-1, -1, -1], [0.25, 0.5])
200 ];
201
202 let index_data: &[u16] = &[
203 0, 1, 3, 2, 3, 1, 4, 5, 7, 6, 7, 5, 8, 9, 11, 10, 11, 9, 12, 13, 15, 14, 15, 13, 16, 17, 19, 18, 19, 17, 20, 21, 23, 22, 23, 21 ];
210
211 let nfaces = index_data.len() as u64 / 6;
212 (vertex_data.to_vec(), index_data.to_vec(), FaceInf{
213 nfaces,
214 il: (0..=nfaces).map(|i| i * 6).collect(),
215 tf: tf}) }
217
218pub fn load_texels(fname: &str)
220 -> Result<((u32, u32, u32, u32), Vec<u8>), Box<dyn Error>> {
221 let im = image::open(fname)?; let (h, w) = (im.height(), im.width());
223let buf = im.into_rgba8().to_vec(); let bytes_per_row = buf.len() as u32 / h; let d = bytes_per_row / w; println!("{} {} {} {} {}", h, w, d, bytes_per_row, buf.len());
235 Ok(((h, w, d, bytes_per_row), buf))
236}
237
238pub fn create_texels_rgba(size: usize, cols4u: &Vec<&[u8; 4]>)
240 -> ((u32, u32, u32, u32), Vec<u8>) {
241 let mut hwd = (size as u32, size as u32, 4, 0);
244 hwd.3 = hwd.2 * hwd.1;
245 (hwd, (0..(hwd.3 * hwd.0) as usize).map(|id| {
246 let bpr = 256 * 4;
247 let v = id / bpr;
248 let w = id % bpr;
249 let u = w / 4;
250 (if v < 128 {
251 if u < 128 { cols4u[0] } else { cols4u[1] }
252 } else {
253 if u < 128 { cols4u[2] } else { cols4u[3] }
254 })[w % 4]
255 }).collect())
256}
257
258pub fn create_texels_mandelbrot_4c(size: usize, col4f: &[f32; 4])
260 -> ((u32, u32, u32, u32), Vec<u8>) {
261 let mut hwd = (size as u32, size as u32, 4, 0);
265 hwd.3 = hwd.2 * hwd.1;
266 (hwd, (0..(hwd.3 * hwd.0) as usize).map(|id| { let c = id / 4;
268 let cx = 3.0 * (c % size) as f32 / (size - 1) as f32 - 2.0;
270 let cy = 2.0 * (c / size) as f32 / (size - 1) as f32 - 1.0;
271 let (mut x, mut y, mut count) = (cx, cy, 0);
272 while count < 0xFF && x * x + y * y < 4.0 {
273 let old_x = x;
274 x = x * x - y * y + cx;
275 y = 2.0 * old_x * y + cy;
276 count += 1;
277 }
278 ((1.0 - (count as f32 / 255.0) * col4f[id % 4]) * 255.0) as u8
279 }).collect())
280}
281
282#[derive(Debug)]
284pub struct YRP {
285 pub yaw: f32,
287 pub roll: f32,
289 pub pitch: f32,
291 pub tick: u64
293}
294
295#[derive(Debug)]
297pub struct CameraAngle {
298 pub pos: glam::Vec3,
300 pub lookat: glam::Vec3,
302 pub top: glam::Vec3
304}
305
306impl CameraAngle {
308 pub fn new(pos: glam::Vec3, lookat: glam::Vec3, top: glam::Vec3) -> Self {
310 CameraAngle{pos, lookat, top}
311 }
312
313 pub fn from_yrp(yrp: &YRP) -> Self {
315 log::warn!("y:{} r:{} p:{}", yrp.yaw, yrp.roll, yrp.pitch);
316 let cs = |t: f32| {let r = t * 3.14159 / 180.0; (r.cos(), r.sin())};
317 let (yc, ys) = cs(yrp.yaw);
318 let (rc, rs) = cs(yrp.roll);
319 let (pc, ps) = cs(yrp.pitch);
320 let (tc, _ts) = cs(yrp.tick as f32);
321 let radius = (tc + 2.0) * 2.0; let (radius_c, radius_s) = (radius * pc, radius * ps);
323 let pos = glam::Vec3::new(radius_c * yc, radius_c * ys, radius_s);
324 let lookat = glam::Vec3::ZERO;
325 let top = glam::Vec3::new(yc * rs, -ys * rs, rc); log::warn!("{:5.2} {:5.2} {:5.2} {:5.2} {:5.2} {:5.2}",
327 pos.x, pos.y, pos.z, top.x, top.y, top.z);
328 CameraAngle{pos, lookat, top}
329 }
330
331 pub fn generate_mvp(&self, aspect_ratio: f32) -> glam::Mat4 {
333 let projection = glam::Mat4::perspective_rh(
334 consts::FRAC_PI_4, aspect_ratio, 1.0, 10.0);
335 let view = glam::Mat4::look_at_rh(self.pos, self.lookat, self.top); projection * view
337 }
338}
339
340#[repr(C)]
342#[derive(Debug)]
343pub struct TexSZ {
344 pub w: u32,
346 pub h: u32,
348 pub ext: [u32; 2]
350}
351
352impl AsRef<[u32; 4]> for TexSZ {
354 fn as_ref(&self) -> &[u32; 4] {
356unsafe {
357 std::slice::from_raw_parts(&self.w as *const u32, 4).try_into().unwrap()
358}
359 }
360}
361
362#[derive(Debug)]
364pub struct TextureBindGroup {
365 pub group: wgpu::BindGroup,
367 pub sz: TexSZ,
369 pub buf: wgpu::Buffer
371}
372
373#[derive(Debug)]
375pub struct WG {
376 pub vips: Vec<VIP>,
378 pub bind_group: Vec<TextureBindGroup>,
380 pub bg: usize,
382 pub mvp: glam::Mat4,
384 pub uniform_buf: wgpu::Buffer,
386 pub pipeline: wgpu::RenderPipeline,
388 pub pipeline_wire: Option<wgpu::RenderPipeline>,
390 pub wire: bool
392}
393
394macro_rules! draw_vip {
396 ($self: ident, $rp: ident, $vbuf: ident, ($vs: expr, $ve: expr), $ibuf: ident, ($is: expr, $ie: expr), $tid: expr, $icnt: expr) => { $rp.push_debug_group("Prepare data for draw.");
401 $rp.set_pipeline(&$self.pipeline);
402 $rp.set_bind_group(0, &$self.bind_group[$tid].group, &[]);
403 $rp.set_index_buffer($ibuf.slice($is..$ie), wgpu::IndexFormat::Uint16);
404 $rp.set_vertex_buffer(0, $vbuf.slice($vs..$ve));
405 $rp.pop_debug_group();
406 $rp.insert_debug_marker("Draw!");
407 if !&$self.wire {
408 $rp.draw_indexed(0..$icnt, 0, 0..1);
409 }
410 if let Some(ref pipe) = &$self.pipeline_wire {
411 $rp.set_pipeline(pipe);
412 $rp.draw_indexed(0..$icnt, 0, 0..1);
413 }
414 }
415}
416
417impl WG {
419 pub fn update_matrix(
421 &mut self,
422 config: &wgpu::SurfaceConfiguration,
423 _device: &wgpu::Device,
424 queue: &wgpu::Queue,
425 yrp: &YRP) {
426 self.mvp = CameraAngle::from_yrp(yrp).generate_mvp(
427 config.width as f32 / config.height as f32);
428 queue.write_buffer(&self.uniform_buf, 0,
429 bytemuck::cast_slice(self.mvp.as_ref())); }
431
432 pub fn draw(
434 &mut self,
435 view: &wgpu::TextureView,
436 device: &wgpu::Device,
437 queue: &wgpu::Queue) {
438 device.push_error_scope(wgpu::ErrorFilter::Validation);
439 let mut encoder = device.create_command_encoder(
440 &wgpu::CommandEncoderDescriptor{label: None});
441 let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor{
442 label: None,
443 color_attachments: &[Some(wgpu::RenderPassColorAttachment{
444 view,
445 resolve_target: None,
446 ops: wgpu::Operations{
447 load: wgpu::LoadOp::Clear(
448 wgpu::Color{r: 0.1, g: 0.2, b: 0.3, a: 1.0}),
449 store: true
450 }
451 })],
452 depth_stencil_attachment: None
453 });
454 for VIP{vs: vertex_buf, is: index_buf, p: fi} in &self.vips {
455for i in 0..fi.nfaces {
468 let isz = std::mem::size_of::<u16>() as u64; let ip_s = fi.il[i as usize] * isz; let ip_e = fi.il[i as usize + 1] * isz; let ipf = (ip_e - ip_s) / isz; let vsz = std::mem::size_of::<Vertex>() as u64; let vpf = (vertex_buf.size() / vsz) / fi.nfaces; let (vp_s, vp_e) = (0, fi.nfaces * vpf * vsz); let tid = (fi.tf)((i as usize, self.bg, self.bind_group.len()));
479 draw_vip!(self, rpass,
480 vertex_buf, (vp_s, vp_e), index_buf, (ip_s, ip_e),
482 tid, ipf as u32);
483 }
484}
486 drop(rpass); queue.submit(Some(encoder.finish()));
488 }
489}