@@ 90,6 90,33 @@ impl Screen {
self.old_list.push(index);
}
}
+
+ fn line(&mut self, x0: u32, y0: u32, x1: u32, y1: u32, px: [u8; 4]) {
+ let dx = i32::abs(x1 as i32 - x0 as i32);
+ let dy = i32::abs(y1 as i32 - y0 as i32);
+ let sx = if x0 < x1 { 1 } else { -1 };
+ let sy = if y0 < y1 { 1 } else { -1 };
+
+ let mut error = if dx > dy { dx } else { -dy } / 2;
+ let mut x = x0 as i32;
+ let mut y = y0 as i32;
+ loop {
+ self.set_pixel(x.try_into().unwrap(), y.try_into().unwrap(), px);
+
+ if x == x1 as i32 && y == y1 as i32 {
+ break;
+ }
+
+ let e = error;
+ if e > -dx {
+ error -= dy;
+ x += sx;
+ }
+ if e < dy {
+ error += dx;
+ y += sy;
+ }
+ }
}
}
@@ 160,28 187,54 @@ fn main() -> Result<(), pixels::Error> {
let rot = Mat4::from_quat(Quat::from_euler(EulerRot::ZYX, yaw, 0.0, pitch));
trans.mul_mat4(&rot)
};
- for atom in &structure.atoms {
- // Find the render position.
- //
- // Orthographic projection.
- // |bx| = |sx 0 0||ax| + |cx|
- // |by| = | 0 0 sy||ay| + |cz|
- // |az|
- //
- // From this, we can derive:
- // bx = sx * ax + cx
- // by = sz * az + cz
- let a = camera.transform_point3(atom.position);
+
+ /// Project a point in world space to screen space.
+ ///
+ /// Orthographic projection.
+ /// |bx| = |sx 0 0||ax| + |cx|
+ /// |by| = | 0 0 sy||ay| + |cz|
+ /// |az|
+ ///
+ /// From this, we can derive:
+ /// bx = sx * ax + cx
+ /// by = sz * az + cz
+ fn project(camera: Mat4, screen: &Screen, zoom: f32, space_point: Vec3) -> (u32, u32) {
+ let a = camera.transform_point3(space_point);
let c = Vec3::new(1.0, 1.0, 1.0);
let s = Mat3::from_cols_array(&[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]);
let b = s.mul_vec3(a) + c;
let (bx, by) = b.xy().into();
let pos: Vec2 = Vec2::new(bx, by); // TODO
+ let screen_pos = pos * zoom + screen.center();
+ (screen_pos.x as u32, screen_pos.y as u32)
+ }
+
+ // Draw a line between the first and last atom that is stored in the Structure.
+ let first = project(
+ camera,
+ &screen,
+ zoom,
+ structure.atoms.first().unwrap().position,
+ );
+ let last = project(
+ camera,
+ &screen,
+ zoom,
+ structure.atoms.last().unwrap().position,
+ );
+ screen.line(first.0, first.1, last.0, last.1, [0xff; Screen::PIXEL_SIZE]);
+ for dy in 0..3 {
+ for dx in 0..3 {
+ screen.set_pixel(first.0 + dx, first.1 + dy, [0xff, 0x00, 0xff, 0xff]);
+ screen.set_pixel(last.0 + dx, last.1 + dy, [0xff, 0x00, 0xff, 0xff]);
+ }
+ }
+
+ for atom in &structure.atoms {
+ let (x, y) = project(camera, &screen, zoom, atom.position);
// Render that onto the screen.
- let screen_pos = pos * zoom + screen.center();
- let (x, y) = (screen_pos.x as u32, screen_pos.y as u32);
if screen.contains(x, y) {
let depth = atom.atomnum as f32 / n_atoms as f32;
let px = {