Showing
2 changed files
with
142 additions
and
9 deletions
| @@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
| 21 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | // | 22 | // |
| 23 | use std::cmp; | 23 | use std::cmp; |
| 24 | -use std::fmt::{Formatter, Display, Result}; | 24 | +use std::fmt::{Formatter, Debug, Display, Result}; |
| 25 | use std::ops::{Add, Sub, Div}; | 25 | use std::ops::{Add, Sub, Div}; |
| 26 | use std::sync::mpsc; | 26 | use std::sync::mpsc; |
| 27 | 27 | ||
| @@ -46,6 +46,10 @@ pub trait Drawable<T> { | @@ -46,6 +46,10 @@ pub trait Drawable<T> { | ||
| 46 | fn plot(&self) -> Coordinates<T>; | 46 | fn plot(&self) -> Coordinates<T>; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | +pub trait Fillable<T> { | ||
| 50 | + fn fill(&self) -> Coordinates<T>; | ||
| 51 | +} | ||
| 52 | + | ||
| 49 | #[derive(Debug, Clone, Copy)] | 53 | #[derive(Debug, Clone, Copy)] |
| 50 | pub struct Coordinate<T>(pub i32, pub i32, pub T); | 54 | pub struct Coordinate<T>(pub i32, pub i32, pub T); |
| 51 | 55 | ||
| @@ -82,15 +86,15 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | @@ -82,15 +86,15 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | ||
| 82 | 86 | ||
| 83 | let dx = (bx - ax).abs(); | 87 | let dx = (bx - ax).abs(); |
| 84 | let sx :i32 = if ax < bx { 1 } else { -1 }; | 88 | let sx :i32 = if ax < bx { 1 } else { -1 }; |
| 85 | - let dy = -(by - ay).abs(); | 89 | + let dy = (by - ay).abs(); |
| 86 | let sy :i32 = if ay < by { 1 } else { -1 }; | 90 | let sy :i32 = if ay < by { 1 } else { -1 }; |
| 87 | - let size = cmp::max(dx, -dy); | 91 | + let size = cmp::max(dx, dy); |
| 88 | let dz = (bz - az) / size.into(); | 92 | let dz = (bz - az) / size.into(); |
| 89 | 93 | ||
| 90 | let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into()) | 94 | let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into()) |
| 91 | ; (size as usize) + 1); | 95 | ; (size as usize) + 1); |
| 92 | v[0] = Coordinate(ax, ay, az); | 96 | v[0] = Coordinate(ax, ay, az); |
| 93 | - inner(&mut v, bx, by, dx, dy, sx, sy, dz, dx + dy); | 97 | + inner(&mut v, bx, by, dx, -dy, sx, sy, dz, dx - dy); |
| 94 | v | 98 | v |
| 95 | } | 99 | } |
| 96 | } | 100 | } |
| @@ -258,6 +262,129 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | @@ -258,6 +262,129 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | ||
| 258 | } | 262 | } |
| 259 | } | 263 | } |
| 260 | 264 | ||
| 265 | +impl<T> Fillable<T> for Polygon<T> | ||
| 266 | +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | ||
| 267 | + + Debug + Clone + Copy + From<i32> { | ||
| 268 | + fn fill(&self) -> Coordinates<T> { | ||
| 269 | + | ||
| 270 | + /* bresenham kind of thing to get the outer x values for each y of one | ||
| 271 | + * edge of the polygon. */ | ||
| 272 | + fn walk_edge<T>( a :Coordinate<T> | ||
| 273 | + , b :Coordinate<T> ) -> Vec<Coordinate<T>> | ||
| 274 | + where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | ||
| 275 | + + From<i32> + Debug + Copy { | ||
| 276 | + | ||
| 277 | + let Coordinate(mut x, mut y, mut z) = a; | ||
| 278 | + let Coordinate( bx, by, bz) = b; | ||
| 279 | + | ||
| 280 | + // next should be called with the negative of this… but dz depends | ||
| 281 | + // on the positive this. | ||
| 282 | + let dy = -(by - y).abs(); | ||
| 283 | + let dx = (bx - x).abs(); | ||
| 284 | + let sx = if x < bx { 1 } else { -1 }; | ||
| 285 | + let dz = (bz - z) / (-dy).into(); | ||
| 286 | + let mut err = dx + dy; | ||
| 287 | + | ||
| 288 | + let mut v = Vec::<Coordinate<T>>::with_capacity((-dy) as usize); | ||
| 289 | + | ||
| 290 | + while y != by { | ||
| 291 | + match (2*err >= dy, 2*err <= dx) { | ||
| 292 | + (true, false) => { x = x + sx | ||
| 293 | + ; err = err + dy }, | ||
| 294 | + (false, true) => { v.push(Coordinate(x, y, z)) | ||
| 295 | + ; y = y + 1 | ||
| 296 | + ; z = z + dz | ||
| 297 | + ; err = err + dx }, | ||
| 298 | + _ => { v.push(Coordinate(x, y, z)) | ||
| 299 | + ; x = x + sx | ||
| 300 | + ; y = y + 1 | ||
| 301 | + ; z = z + dz | ||
| 302 | + ; err = err + dx + dy }, | ||
| 303 | + } | ||
| 304 | + } | ||
| 305 | + | ||
| 306 | + v | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + fn next_y<T>( cs :&[Coordinate<T>] | ||
| 310 | + , c :usize | ||
| 311 | + , f :&dyn Fn(usize) -> usize) -> Option<usize> { | ||
| 312 | + fn inner<T>( cs :&[Coordinate<T>] | ||
| 313 | + , c :usize | ||
| 314 | + , n :usize | ||
| 315 | + , f :&dyn Fn(usize) -> usize) -> Option<usize> { | ||
| 316 | + if c == n { | ||
| 317 | + None | ||
| 318 | + } else { | ||
| 319 | + let Coordinate(_, cy, _) = cs[c]; | ||
| 320 | + let Coordinate(_, ny, _) = cs[n]; | ||
| 321 | + | ||
| 322 | + match ny.cmp(&cy) { | ||
| 323 | + cmp::Ordering::Less => None, | ||
| 324 | + cmp::Ordering::Equal => inner(cs, c, f(n), f), | ||
| 325 | + cmp::Ordering::Greater => Some(n), | ||
| 326 | + } | ||
| 327 | + } | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + inner(cs, c, f(c), f) | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + let Polygon(Coordinates(cs)) = self; | ||
| 334 | + | ||
| 335 | + let vert_min = cs.iter().enumerate() | ||
| 336 | + . fold( None | ||
| 337 | + , |acc, x| match acc { | ||
| 338 | + None => Some(x), | ||
| 339 | + Some(a) => { | ||
| 340 | + let Coordinate(_, ay, _) = a.1; | ||
| 341 | + let Coordinate(_, xy, _) = x.1; | ||
| 342 | + if xy < ay {Some(x)} else {Some(a)} } } ) | ||
| 343 | + . unwrap().0; | ||
| 344 | + | ||
| 345 | + println!("== vert_min: [{:?}] - {:?}", vert_min, cs[vert_min]); | ||
| 346 | + | ||
| 347 | + let right = |x :usize| (x + 1) % cs.len(); | ||
| 348 | + let left = |x :usize| if x == 0 { cs.len() - 1 } else { x - 1 }; | ||
| 349 | + | ||
| 350 | + let mut r = (vert_min, next_y(cs, vert_min, &right)); | ||
| 351 | + let mut l = (vert_min, next_y(cs, vert_min, &left)); | ||
| 352 | + | ||
| 353 | + let mut l_edge :Vec<Coordinate<T>> = Vec::new(); | ||
| 354 | + let mut r_edge :Vec<Coordinate<T>> = Vec::new(); | ||
| 355 | + | ||
| 356 | + while l.1 != None || r.1 != None { | ||
| 357 | + match l.1 { | ||
| 358 | + None => {}, | ||
| 359 | + Some(a) => { | ||
| 360 | + println!("== l: [{:?}] - {:?}", l, cs[a]); | ||
| 361 | + l_edge.append(&mut walk_edge(cs[l.0], cs[a])); | ||
| 362 | + l = (a, next_y(cs, a, &left)); | ||
| 363 | + }, | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + match r.1 { | ||
| 367 | + None => {}, | ||
| 368 | + Some(a) => { | ||
| 369 | + println!("== r: [{:?}] - {:?}", r, cs[a]); | ||
| 370 | + r_edge.append(&mut walk_edge(cs[r.0], cs[a])); | ||
| 371 | + r = (a, next_y(cs, a, &right)); | ||
| 372 | + } | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + println!("== [{}] {:?}", l_edge.len(), l_edge); | ||
| 377 | + println!("== [{}] {:?}", r_edge.len(), r_edge); | ||
| 378 | + | ||
| 379 | + // TODO we always miss the last scanline… | ||
| 380 | + // TODO check what happend with at least 2 vertices with same y and | ||
| 381 | + // different x… | ||
| 382 | + // loop though edges… | ||
| 383 | + | ||
| 384 | + Coordinates(Vec::<Coordinate<T>>::new()) | ||
| 385 | + } | ||
| 386 | +} | ||
| 387 | + | ||
| 261 | impl<T> Display for Polygon<T> where T: Copy { | 388 | impl<T> Display for Polygon<T> where T: Copy { |
| 262 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { | 389 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { |
| 263 | let Polygon(a) = self; | 390 | let Polygon(a) = self; |
| @@ -22,7 +22,7 @@ use std::convert::{From, Into}; | @@ -22,7 +22,7 @@ use std::convert::{From, Into}; | ||
| 22 | use std::ops::{Add,Sub,Neg,Mul,Div}; | 22 | use std::ops::{Add,Sub,Neg,Mul,Div}; |
| 23 | use std::fmt::Debug; | 23 | use std::fmt::Debug; |
| 24 | 24 | ||
| 25 | -use crate::easel::{Canvas,Coordinate,Coordinates,Polygon}; | 25 | +use crate::easel::{Canvas,Coordinate,Coordinates,Polygon,Fillable}; |
| 26 | use crate::transform::{TMatrix, Transformable}; | 26 | use crate::transform::{TMatrix, Transformable}; |
| 27 | use crate::trigonometry::Trig; | 27 | use crate::trigonometry::Trig; |
| 28 | use crate::vector::Vector; | 28 | use crate::vector::Vector; |
| @@ -347,7 +347,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | @@ -347,7 +347,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 347 | // matrix we do not need to do it here. | 347 | // matrix we do not need to do it here. |
| 348 | let to_coord = |p :&usize| { | 348 | let to_coord = |p :&usize| { |
| 349 | let Point(v, _) = camera.project(self.points[*p]); | 349 | let Point(v, _) = camera.project(self.points[*p]); |
| 350 | - println!("== {:?} / {:?}", self.points[*p], (v.z() - 1.into()).recip()); | 350 | + // println!("== {:?} / {:?}", self.points[*p], (v.z() - 1.into()).recip()); |
| 351 | Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into()) | 351 | Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into()) |
| 352 | }; | 352 | }; |
| 353 | let to_poly = |f :&Face<T>| { | 353 | let to_poly = |f :&Face<T>| { |
| @@ -361,6 +361,8 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | @@ -361,6 +361,8 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 361 | / (n.mag() * light.dir().mag()), | 361 | / (n.mag() * light.dir().mag()), |
| 362 | }; | 362 | }; |
| 363 | 363 | ||
| 364 | + // this if represents a first simple backface culling | ||
| 365 | + // approach. We only return face that face towards us. | ||
| 364 | if lf < 0.into() { | 366 | if lf < 0.into() { |
| 365 | r = r * -lf; | 367 | r = r * -lf; |
| 366 | g = g * -lf; | 368 | g = g * -lf; |
| @@ -370,14 +372,18 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | @@ -370,14 +372,18 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 370 | | (g.round() as u32) << 8 | 372 | | (g.round() as u32) << 8 |
| 371 | | (b.round() as u32); | 373 | | (b.round() as u32); |
| 372 | 374 | ||
| 375 | + (&pg).fill(); | ||
| 376 | + | ||
| 373 | Some((pg, c)) | 377 | Some((pg, c)) |
| 374 | } else { | 378 | } else { |
| 375 | None | 379 | None |
| 376 | }}; | 380 | }}; |
| 377 | 381 | ||
| 378 | - let mut ps :Vec<(Polygon<T>, u32)> = self.faces.iter() | ||
| 379 | - . filter_map(to_poly).collect(); | ||
| 380 | - ps.sort_by(|a, b| a.1.cmp(&b.1)); | 382 | + let ps :Vec<(Polygon<T>, u32)> = self.faces.iter() |
| 383 | + . filter_map(to_poly).collect(); | ||
| 384 | + // this sorts by the color value which is no longer neccessary as soon | ||
| 385 | + // as the z-buffer is complete. | ||
| 386 | + // ps.sort_by(|a, b| a.1.cmp(&b.1)); | ||
| 381 | ps | 387 | ps |
| 382 | } | 388 | } |
| 383 | } | 389 | } |
Please
register
or
login
to post a comment