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