Some triangle testing
This commit is contained in:
parent
225416353f
commit
6ba531a957
|
@ -16,15 +16,15 @@ impl<T: SignedNum> Bresenham<T> {
|
|||
let start = octant.to(start);
|
||||
let end = octant.to(end);
|
||||
|
||||
let delta_x = end.0 - start.0;
|
||||
let delta_y = end.1 - start.1;
|
||||
let delta_x = end.x - start.x;
|
||||
let delta_y = end.y - start.y;
|
||||
|
||||
Self {
|
||||
delta_x,
|
||||
delta_y,
|
||||
octant,
|
||||
point: start,
|
||||
end_x: end.0,
|
||||
end_x: end.x,
|
||||
error: delta_y - delta_x,
|
||||
}
|
||||
}
|
||||
|
@ -38,15 +38,15 @@ where
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.point.0 <= self.end_x {
|
||||
if self.point.x <= self.end_x {
|
||||
let point = self.octant.from(self.point);
|
||||
|
||||
if self.error >= T::zero() {
|
||||
self.point.1 += T::one();
|
||||
self.point.y += T::one();
|
||||
self.error -= self.delta_x;
|
||||
}
|
||||
|
||||
self.point.0 += T::one();
|
||||
self.point.x += T::one();
|
||||
self.error += self.delta_y;
|
||||
|
||||
Some(point)
|
||||
|
|
41
src/drawing/device.rs
Normal file
41
src/drawing/device.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use super::Point;
|
||||
use crate::writers::{GraphicsWriter, Screen};
|
||||
use core::cmp::{max, min};
|
||||
|
||||
pub trait Device<Color>
|
||||
where
|
||||
Self: Screen + GraphicsWriter<Color>,
|
||||
Color: Clone + Copy,
|
||||
{
|
||||
fn draw_triangle(&self, v0: &Point<i32>, v1: &Point<i32>, v2: &Point<i32>, color: Color) {
|
||||
let screen_width = self.get_width() as i32;
|
||||
let screen_height = self.get_height() as i32;
|
||||
let mut min_x = min(v0.x, min(v1.x, v2.x));
|
||||
let mut min_y = min(v0.y, min(v1.y, v2.y));
|
||||
let mut max_x = max(v0.x, max(v1.x, v2.x));
|
||||
let mut max_y = max(v0.y, max(v1.y, v2.y));
|
||||
|
||||
min_x = max(min_x, 0);
|
||||
min_y = max(min_y, 0);
|
||||
max_x = min(max_x, screen_width - 1);
|
||||
max_y = min(max_y, screen_height - 1);
|
||||
|
||||
for x in min_x..=max_x {
|
||||
for y in min_y..=max_y {
|
||||
let p = Point::new(x, y);
|
||||
let w0 = orient2d(v1, v2, &p);
|
||||
let w1 = orient2d(v2, v0, &p);
|
||||
let w2 = orient2d(&v0, &v1, &p);
|
||||
|
||||
if w0 >= 0 && w1 >= 0 && w2 >= 0 {
|
||||
self.set_pixel(x as usize, y as usize, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn orient2d(a: &Point<i32>, b: &Point<i32>, c: &Point<i32>) -> i32 {
|
||||
(b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
|
||||
}
|
|
@ -3,13 +3,25 @@
|
|||
use num_traits::{NumAssignOps, NumCast, Signed};
|
||||
|
||||
mod bresenham;
|
||||
mod device;
|
||||
mod octant;
|
||||
|
||||
pub(crate) use bresenham::Bresenham;
|
||||
pub use device::Device;
|
||||
use octant::Octant;
|
||||
|
||||
/// A point in 2D space.
|
||||
pub type Point<T> = (T, T);
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Point<T> {
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
}
|
||||
|
||||
impl<T> Point<T> {
|
||||
pub fn new(x: T, y: T) -> Point<T> {
|
||||
Point { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait SignedNum: Signed + Ord + Copy + NumCast + NumAssignOps {
|
||||
fn cast<T: NumCast>(value: T) -> Self {
|
||||
|
|
|
@ -15,8 +15,8 @@ impl Octant {
|
|||
T: Sub<Output = T> + Neg<Output = T> + PartialOrd + Zero,
|
||||
{
|
||||
let mut value = 0;
|
||||
let mut dx = end.0 - start.0;
|
||||
let mut dy = end.1 - start.1;
|
||||
let mut dx = end.x - start.x;
|
||||
let mut dy = end.y - start.y;
|
||||
|
||||
if dy < T::zero() {
|
||||
dx = -dx;
|
||||
|
@ -45,14 +45,14 @@ impl Octant {
|
|||
T: Neg<Output = T>,
|
||||
{
|
||||
match self.value {
|
||||
0 => (point.0, point.1),
|
||||
1 => (point.1, point.0),
|
||||
2 => (point.1, -point.0),
|
||||
3 => (-point.0, point.1),
|
||||
4 => (-point.0, -point.1),
|
||||
5 => (-point.1, -point.0),
|
||||
6 => (-point.1, point.0),
|
||||
7 => (point.0, -point.1),
|
||||
0 => Point::new(point.x, point.y),
|
||||
1 => Point::new(point.y, point.x),
|
||||
2 => Point::new(point.y, -point.x),
|
||||
3 => Point::new(-point.x, point.y),
|
||||
4 => Point::new(-point.x, -point.y),
|
||||
5 => Point::new(-point.y, -point.x),
|
||||
6 => Point::new(-point.y, point.x),
|
||||
7 => Point::new(point.x, -point.y),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -61,14 +61,14 @@ impl Octant {
|
|||
#[inline]
|
||||
pub fn from<T: Neg<Output = T>>(&self, point: Point<T>) -> Point<T> {
|
||||
match self.value {
|
||||
0 => (point.0, point.1),
|
||||
1 => (point.1, point.0),
|
||||
2 => (-point.1, point.0),
|
||||
3 => (-point.0, point.1),
|
||||
4 => (-point.0, -point.1),
|
||||
5 => (-point.1, -point.0),
|
||||
6 => (point.1, -point.0),
|
||||
7 => (point.0, -point.1),
|
||||
0 => Point::new(point.x, point.y),
|
||||
1 => Point::new(point.y, point.x),
|
||||
2 => Point::new(-point.y, point.x),
|
||||
3 => Point::new(-point.x, point.y),
|
||||
4 => Point::new(-point.x, -point.y),
|
||||
5 => Point::new(-point.y, -point.x),
|
||||
6 => Point::new(point.y, -point.x),
|
||||
7 => Point::new(point.x, -point.y),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{GraphicsWriter, Screen};
|
||||
use crate::{
|
||||
colors::DEFAULT_PALETTE,
|
||||
drawing::{Bresenham, Point},
|
||||
drawing::{Bresenham, Device, Point},
|
||||
vga::{Vga, VideoMode, VGA},
|
||||
};
|
||||
use font8x8::UnicodeFonts;
|
||||
|
@ -53,6 +53,8 @@ impl Screen for Graphics320x200x256 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Device<u8> for Graphics320x200x256 {}
|
||||
|
||||
impl GraphicsWriter<u8> for Graphics320x200x256 {
|
||||
fn clear_screen(&self, color: u8) {
|
||||
for x in 0..WIDTH {
|
||||
|
@ -62,7 +64,7 @@ impl GraphicsWriter<u8> for Graphics320x200x256 {
|
|||
}
|
||||
}
|
||||
fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: u8) {
|
||||
for (x, y) in Bresenham::new(start, end) {
|
||||
for Point { x, y } in Bresenham::new(start, end) {
|
||||
self.set_pixel(x as usize, y as usize, color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{GraphicsWriter, Screen};
|
||||
use crate::{
|
||||
colors::{Color16, DEFAULT_PALETTE},
|
||||
drawing::{Bresenham, Point},
|
||||
drawing::{Bresenham, Device, Point},
|
||||
registers::{PlaneMask, WriteMode},
|
||||
vga::{Vga, VideoMode, VGA},
|
||||
};
|
||||
|
@ -51,6 +51,8 @@ impl Screen for Graphics640x480x16 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Device<Color16> for Graphics640x480x16 {}
|
||||
|
||||
impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
||||
fn clear_screen(&self, color: Color16) {
|
||||
self.set_write_mode_2();
|
||||
|
@ -64,7 +66,7 @@ impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
|||
|
||||
fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: Color16) {
|
||||
self.set_write_mode_0(color);
|
||||
for (x, y) in Bresenham::new(start, end) {
|
||||
for Point { x, y } in Bresenham::new(start, end) {
|
||||
self._set_pixel(x as usize, y as usize, color);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue