Commit 721b89a171e06accb01674ba69b18fbc3ce0b237

Authored by Georg Hopp
1 parent df1eb1c0

Start polygon fill

... ... @@ -21,7 +21,7 @@
21 21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 22 //
23 23 use std::cmp;
24   -use std::fmt::{Formatter, Display, Result};
  24 +use std::fmt::{Formatter, Debug, Display, Result};
25 25 use std::ops::{Add, Sub, Div};
26 26 use std::sync::mpsc;
27 27
... ... @@ -46,6 +46,10 @@ pub trait Drawable<T> {
46 46 fn plot(&self) -> Coordinates<T>;
47 47 }
48 48
  49 +pub trait Fillable<T> {
  50 + fn fill(&self) -> Coordinates<T>;
  51 +}
  52 +
49 53 #[derive(Debug, Clone, Copy)]
50 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 86
83 87 let dx = (bx - ax).abs();
84 88 let sx :i32 = if ax < bx { 1 } else { -1 };
85   - let dy = -(by - ay).abs();
  89 + let dy = (by - ay).abs();
86 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 92 let dz = (bz - az) / size.into();
89 93
90 94 let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
91 95 ; (size as usize) + 1);
92 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 98 v
95 99 }
96 100 }
... ... @@ -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 388 impl<T> Display for Polygon<T> where T: Copy {
262 389 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
263 390 let Polygon(a) = self;
... ...
... ... @@ -22,7 +22,7 @@ use std::convert::{From, Into};
22 22 use std::ops::{Add,Sub,Neg,Mul,Div};
23 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 26 use crate::transform::{TMatrix, Transformable};
27 27 use crate::trigonometry::Trig;
28 28 use crate::vector::Vector;
... ... @@ -347,7 +347,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
347 347 // matrix we do not need to do it here.
348 348 let to_coord = |p :&usize| {
349 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 351 Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into())
352 352 };
353 353 let to_poly = |f :&Face<T>| {
... ... @@ -361,6 +361,8 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
361 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 366 if lf < 0.into() {
365 367 r = r * -lf;
366 368 g = g * -lf;
... ... @@ -370,14 +372,18 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
370 372 | (g.round() as u32) << 8
371 373 | (b.round() as u32);
372 374
  375 + (&pg).fill();
  376 +
373 377 Some((pg, c))
374 378 } else {
375 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 387 ps
382 388 }
383 389 }
... ...
Please register or login to post a comment