demo-universe.rs
3.5 kB · rust · 116 lines
1use mrlycore::colors::{shades, INDIGO};2use mrlycore::errors::Result;3use mrlyfig::{ink, iso, save, Board, Color};4use mrlymath::bang::bang;5use mrlymath::three::designs;6use mrlymath::three::faces::quads;7use mrlymath::three::Cell3d;89const NUMBER: usize = 3;10const ROWS: [usize; 5] = [4, 5, 4, 5, 4];11const HALF: f64 = 1.5;1213fn cage(board: &mut Board, cx: f64, cy: f64, s: f64) {14 let corner = |i: usize| {15 let bit = |b: usize| ((i >> b) & 1) as f64 * 2.0 - 1.0;16 let p = iso::project(bit(0) * HALF, bit(1) * HALF, bit(2) * HALF);17 (cx + p.0 * s, cy + p.1 * s)18 };19 for a in 0usize..8 {20 for b in (a + 1)..8 {21 if (a ^ b).count_ones() == 1 {22 board.segment(23 corner(a),24 corner(b),25 s / 24.0,26 ink::mix(ink::line(), ink::dim(), 0.3),27 );28 }29 }30 }31}3233fn stamp(board: &mut Board, cell: &Cell3d, cx: f64, cy: f64, s: f64, shade: [Color; 3]) {34 let mut faces = Vec::new();35 for quad in quads(cell) {36 let n = (37 quad.normal.x as f64,38 quad.normal.y as f64,39 quad.normal.z as f64,40 );41 if n.0 + n.1 + n.2 <= 0.0 {42 continue;43 }44 let tone = if n.2 > 0.0 {45 046 } else if n.1 > 0.0 {47 148 } else {49 250 };51 let pts: Vec<(f64, f64)> = quad52 .verts53 .iter()54 .map(|v| {55 let p = iso::project(v.x as f64 - HALF, v.y as f64 - HALF, v.z as f64 - HALF);56 (cx + p.0 * s, cy + p.1 * s)57 })58 .collect();59 let depth = quad60 .verts61 .iter()62 .map(|v| (v.x + v.y + v.z) as f64)63 .sum::<f64>();64 faces.push((depth, tone, pts));65 }66 faces.sort_by(|a, b| a.0.total_cmp(&b.0));67 for (_, tone, pts) in &faces {68 board.polygon(pts, shade[*tone]);69 let mut ring = pts.clone();70 ring.push(pts[0]);71 board.polyline(&ring, s / 18.0, ink::ground());72 }73}7475fn weight(corner: &[u8]) -> u64 {76 corner77 .iter()78 .map(|bit| if *bit == 0 { 2 } else { 1 })79 .product()80}8182fn main() -> Result<()> {83 let mut board = Board::square();84 let frame = board.frame(0.08);85 let gallery = bang(3).canonical();86 assert_eq!(gallery.len(), 22);87 assert_eq!(ROWS.iter().sum::<usize>(), gallery.len());88 let shade = shades(INDIGO);89 let (mx, _) = frame.center();90 let pitch = (frame.w / 5.0, frame.h / 5.0);91 let s = (pitch.0 * 0.46 / (3.0 * 0.866_025_403_784_438_6)).min(pitch.1 * 0.46 / 3.0);92 let mut taken = 0usize;93 for (r, count) in ROWS.iter().enumerate() {94 let cy = frame.y + (r as f64 + 0.5) * pitch.1;95 for j in 0..*count {96 let design = &gallery[taken];97 let cx = mx + (j as f64 - (*count as f64 - 1.0) / 2.0) * pitch.0;98 let solid = designs::create(design.i, NUMBER, 1, 2)?;99 assert_eq!((solid.width(), solid.height(), solid.depth()), (3, 3, 3));100 assert_eq!(101 solid.types().sum(),102 design103 .rule()104 .iter()105 .map(|c| weight(c.as_slice()))106 .sum::<u64>()107 );108 cage(&mut board, cx, cy, s);109 stamp(&mut board, &solid, cx, cy, s, shade);110 taken += 1;111 }112 }113 assert_eq!(taken, 22);114 save("demo-universe", &board)?;115 Ok(())116}