~ma3ke/laurel

e320066be86937466c0e37079c9f866c81dbe51a — Marieke Westendorp 27 days ago c6d8f1b
Implement line drawing
1 files changed, 67 insertions(+), 14 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +67 -14
@@ 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 = {