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 start = octant.to(start);
|
||||||
let end = octant.to(end);
|
let end = octant.to(end);
|
||||||
|
|
||||||
let delta_x = end.0 - start.0;
|
let delta_x = end.x - start.x;
|
||||||
let delta_y = end.1 - start.1;
|
let delta_y = end.y - start.y;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
delta_x,
|
delta_x,
|
||||||
delta_y,
|
delta_y,
|
||||||
octant,
|
octant,
|
||||||
point: start,
|
point: start,
|
||||||
end_x: end.0,
|
end_x: end.x,
|
||||||
error: delta_y - delta_x,
|
error: delta_y - delta_x,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,15 +38,15 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
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);
|
let point = self.octant.from(self.point);
|
||||||
|
|
||||||
if self.error >= T::zero() {
|
if self.error >= T::zero() {
|
||||||
self.point.1 += T::one();
|
self.point.y += T::one();
|
||||||
self.error -= self.delta_x;
|
self.error -= self.delta_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.point.0 += T::one();
|
self.point.x += T::one();
|
||||||
self.error += self.delta_y;
|
self.error += self.delta_y;
|
||||||
|
|
||||||
Some(point)
|
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};
|
use num_traits::{NumAssignOps, NumCast, Signed};
|
||||||
|
|
||||||
mod bresenham;
|
mod bresenham;
|
||||||
|
mod device;
|
||||||
mod octant;
|
mod octant;
|
||||||
|
|
||||||
pub(crate) use bresenham::Bresenham;
|
pub(crate) use bresenham::Bresenham;
|
||||||
|
pub use device::Device;
|
||||||
use octant::Octant;
|
use octant::Octant;
|
||||||
|
|
||||||
/// A point in 2D space.
|
/// 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 {
|
pub(crate) trait SignedNum: Signed + Ord + Copy + NumCast + NumAssignOps {
|
||||||
fn cast<T: NumCast>(value: T) -> Self {
|
fn cast<T: NumCast>(value: T) -> Self {
|
||||||
|
|
|
@ -15,8 +15,8 @@ impl Octant {
|
||||||
T: Sub<Output = T> + Neg<Output = T> + PartialOrd + Zero,
|
T: Sub<Output = T> + Neg<Output = T> + PartialOrd + Zero,
|
||||||
{
|
{
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let mut dx = end.0 - start.0;
|
let mut dx = end.x - start.x;
|
||||||
let mut dy = end.1 - start.1;
|
let mut dy = end.y - start.y;
|
||||||
|
|
||||||
if dy < T::zero() {
|
if dy < T::zero() {
|
||||||
dx = -dx;
|
dx = -dx;
|
||||||
|
@ -45,14 +45,14 @@ impl Octant {
|
||||||
T: Neg<Output = T>,
|
T: Neg<Output = T>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
0 => (point.0, point.1),
|
0 => Point::new(point.x, point.y),
|
||||||
1 => (point.1, point.0),
|
1 => Point::new(point.y, point.x),
|
||||||
2 => (point.1, -point.0),
|
2 => Point::new(point.y, -point.x),
|
||||||
3 => (-point.0, point.1),
|
3 => Point::new(-point.x, point.y),
|
||||||
4 => (-point.0, -point.1),
|
4 => Point::new(-point.x, -point.y),
|
||||||
5 => (-point.1, -point.0),
|
5 => Point::new(-point.y, -point.x),
|
||||||
6 => (-point.1, point.0),
|
6 => Point::new(-point.y, point.x),
|
||||||
7 => (point.0, -point.1),
|
7 => Point::new(point.x, -point.y),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,14 @@ impl Octant {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from<T: Neg<Output = T>>(&self, point: Point<T>) -> Point<T> {
|
pub fn from<T: Neg<Output = T>>(&self, point: Point<T>) -> Point<T> {
|
||||||
match self.value {
|
match self.value {
|
||||||
0 => (point.0, point.1),
|
0 => Point::new(point.x, point.y),
|
||||||
1 => (point.1, point.0),
|
1 => Point::new(point.y, point.x),
|
||||||
2 => (-point.1, point.0),
|
2 => Point::new(-point.y, point.x),
|
||||||
3 => (-point.0, point.1),
|
3 => Point::new(-point.x, point.y),
|
||||||
4 => (-point.0, -point.1),
|
4 => Point::new(-point.x, -point.y),
|
||||||
5 => (-point.1, -point.0),
|
5 => Point::new(-point.y, -point.x),
|
||||||
6 => (point.1, -point.0),
|
6 => Point::new(point.y, -point.x),
|
||||||
7 => (point.0, -point.1),
|
7 => Point::new(point.x, -point.y),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{GraphicsWriter, Screen};
|
use super::{GraphicsWriter, Screen};
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::DEFAULT_PALETTE,
|
colors::DEFAULT_PALETTE,
|
||||||
drawing::{Bresenham, Point},
|
drawing::{Bresenham, Device, Point},
|
||||||
vga::{Vga, VideoMode, VGA},
|
vga::{Vga, VideoMode, VGA},
|
||||||
};
|
};
|
||||||
use font8x8::UnicodeFonts;
|
use font8x8::UnicodeFonts;
|
||||||
|
@ -53,6 +53,8 @@ impl Screen for Graphics320x200x256 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Device<u8> for Graphics320x200x256 {}
|
||||||
|
|
||||||
impl GraphicsWriter<u8> for Graphics320x200x256 {
|
impl GraphicsWriter<u8> for Graphics320x200x256 {
|
||||||
fn clear_screen(&self, color: u8) {
|
fn clear_screen(&self, color: u8) {
|
||||||
for x in 0..WIDTH {
|
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) {
|
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);
|
self.set_pixel(x as usize, y as usize, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{GraphicsWriter, Screen};
|
use super::{GraphicsWriter, Screen};
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::{Color16, DEFAULT_PALETTE},
|
colors::{Color16, DEFAULT_PALETTE},
|
||||||
drawing::{Bresenham, Point},
|
drawing::{Bresenham, Device, Point},
|
||||||
registers::{PlaneMask, WriteMode},
|
registers::{PlaneMask, WriteMode},
|
||||||
vga::{Vga, VideoMode, VGA},
|
vga::{Vga, VideoMode, VGA},
|
||||||
};
|
};
|
||||||
|
@ -51,6 +51,8 @@ impl Screen for Graphics640x480x16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Device<Color16> for Graphics640x480x16 {}
|
||||||
|
|
||||||
impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
||||||
fn clear_screen(&self, color: Color16) {
|
fn clear_screen(&self, color: Color16) {
|
||||||
self.set_write_mode_2();
|
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) {
|
fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: Color16) {
|
||||||
self.set_write_mode_0(color);
|
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);
|
self._set_pixel(x as usize, y as usize, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue