Commit 721b89a171e06accb01674ba69b18fbc3ce0b237

Authored by Georg Hopp
1 parent df1eb1c0

Start polygon fill

@@ -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