Commit 2052a7a843e5740b8efe19164e14b5a9aa30644a

Authored by Georg Hopp
1 parent c1655b4e

user projection matrix

@@ -29,68 +29,76 @@ use crate::vector::Vector; @@ -29,68 +29,76 @@ use crate::vector::Vector;
29 29
30 #[derive(Debug)] 30 #[derive(Debug)]
31 pub struct Polyeder<T> 31 pub struct Polyeder<T>
32 -where T: Add + Sub + Neg + Mul + Div + Copy + Trig { 32 +where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig {
33 points :Vec<Vector<T>>, 33 points :Vec<Vector<T>>,
34 faces :Vec<Vec<usize>>, 34 faces :Vec<Vec<usize>>,
35 } 35 }
36 36
37 pub trait Primitives<T> 37 pub trait Primitives<T>
38 -where T: Add + Sub + Neg + Mul + Div + Copy + Trig + From<i32> { 38 +where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
39 fn transform(&self, m :&TMatrix<T>) -> Self; 39 fn transform(&self, m :&TMatrix<T>) -> Self;
40 fn project(&self, camera :&Camera<T>) -> Vec<Polygon>; 40 fn project(&self, camera :&Camera<T>) -> Vec<Polygon>;
41 } 41 }
42 42
43 pub struct Camera<T> 43 pub struct Camera<T>
44 -where T: Add + Sub + Neg + Mul + Div + Copy + Trig {  
45 - width :T,  
46 - height :T,  
47 - fovx :T,  
48 - fovy :T, 44 +where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
  45 + width :T,
  46 + height :T,
  47 + project :TMatrix<T>,
49 } 48 }
50 49
51 impl<T> Camera<T> 50 impl<T> Camera<T>
52 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> 51 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
53 + Mul<Output = T> + Div<Output = T> 52 + Mul<Output = T> + Div<Output = T>
54 - + Copy + Trig + From<i32> { 53 + + Debug + Copy + Trig + From<i32> {
  54 + // This code assumes that the size of the viewport is always
  55 + // equal to the size of the physical screen… e.g. window/canvas thus some
  56 + // effects can't be done. See book for examples with different viewport
  57 + // and screen sizes.
55 pub fn new(c :&dyn Canvas, angle :i32) -> Self { 58 pub fn new(c :&dyn Canvas, angle :i32) -> Self {
56 - let width = <T as From<i32>>::from(c.width() as i32);  
57 - let height = <T as From<i32>>::from(c.height() as i32);  
58 -  
59 - // The calculations for fovx and fovy are taken from a book, but I  
60 - // have the impression, coming from my limited algebra knowledge,  
61 - // that they are always equal…  
62 - Camera { width: width  
63 - , height: height  
64 - , fovx: T::cot(angle) * width  
65 - , fovy: width / height * T::cot(angle) * height } 59 + let width :T = (c.width() as i32).into();
  60 + let height :T = (c.height() as i32).into();
  61 + let d :T = 1.into();
  62 + let fov = T::cot(angle) * width;
  63 + let wh = width / 2.into();
  64 + let hh = height / 2.into();
  65 +
  66 + Camera { width: width
  67 + , height: height
  68 + , project: TMatrix::new(
  69 + ( fov, 0.into(), wh, 0.into())
  70 + , (0.into(), fov, hh, 0.into())
  71 + , (0.into(), 0.into(), d, 1.into())
  72 + , (0.into(), 0.into(), 1.into(), 0.into()) ) }
66 } 73 }
67 74
68 - pub fn project(&self, v :Vector<T>) -> Coordinate {  
69 - let f2 = From::<i32>::from(2);  
70 - let xs = v.x() / v.z() * self.fovx + self.width / f2;  
71 - let ys = v.y() / v.z() * self.fovy + self.height / f2; 75 + pub fn get_projection(&self) -> TMatrix<T> {
  76 + self.project
  77 + }
72 78
73 - Coordinate(T::round(&xs), T::round(&ys)) 79 + pub fn project(&self, v :Vector<T>) -> Coordinate {
  80 + let p = self.project.apply(&v);
  81 + Coordinate(T::round(&p.x()), T::round(&p.y()))
74 } 82 }
75 } 83 }
76 84
77 impl<T> Polyeder<T> 85 impl<T> Polyeder<T>
78 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> 86 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
79 + Mul<Output = T> + Div<Output = T> 87 + Mul<Output = T> + Div<Output = T>
80 - + Copy + Trig + From<i32> { 88 + + Debug + Copy + Trig + From<i32> {
81 // https://rechneronline.de/pi/tetrahedron.php 89 // https://rechneronline.de/pi/tetrahedron.php
82 pub fn tetrahedron(a :T) -> Polyeder<T> { 90 pub fn tetrahedron(a :T) -> Polyeder<T> {
83 - let f0 :T = From::<i32>::from(0);  
84 - let f3 :T = From::<i32>::from(3);  
85 - let f4 :T = From::<i32>::from(4);  
86 - let f6 :T = From::<i32>::from(6);  
87 - let f12 :T = From::<i32>::from(12); 91 + let f0 :T = 0.into();
  92 + let f3 :T = 3.into();
  93 + let f4 :T = 4.into();
  94 + let f6 :T = 6.into();
  95 + let f12 :T = 12.into();
88 96
89 let yi :T = a / f12 * T::sqrt(f6).unwrap(); 97 let yi :T = a / f12 * T::sqrt(f6).unwrap();
90 let yc :T = a / f4 * T::sqrt(f6).unwrap(); 98 let yc :T = a / f4 * T::sqrt(f6).unwrap();
91 let zi :T = T::sqrt(f3).unwrap() / f6 * a; 99 let zi :T = T::sqrt(f3).unwrap() / f6 * a;
92 let zc :T = T::sqrt(f3).unwrap() / f3 * a; 100 let zc :T = T::sqrt(f3).unwrap() / f3 * a;
93 - let ah :T = a / From::<i32>::from(2); 101 + let ah :T = a / 2.into();
94 102
95 // half the height in y 103 // half the height in y
96 let _yh :T = a / f6 * T::sqrt(f6).unwrap(); 104 let _yh :T = a / f6 * T::sqrt(f6).unwrap();
@@ -130,19 +138,27 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> @@ -130,19 +138,27 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
130 impl<T> Primitives<T> for Polyeder<T> 138 impl<T> Primitives<T> for Polyeder<T>
131 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> 139 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
132 + Mul<Output = T> + Div<Output = T> 140 + Mul<Output = T> + Div<Output = T>
133 - + Copy + Trig + From<i32> + From<i32> { 141 + + Debug + Copy + Trig + From<i32> + From<i32> {
134 fn transform(&self, m :&TMatrix<T>) -> Self { 142 fn transform(&self, m :&TMatrix<T>) -> Self {
135 Polyeder{ points: self.points.iter().map(|p| m.apply(p)).collect() 143 Polyeder{ points: self.points.iter().map(|p| m.apply(p)).collect()
136 , faces: self.faces.to_vec() } 144 , faces: self.faces.to_vec() }
137 } 145 }
138 146
139 - fn project(&self, camera :&Camera<T>) -> Vec<Polygon> { 147 + // TODO for now we assume already prejected vertices (points)
  148 + // in future we need to distinguish more clear between vertex and point
  149 + // and projected_point.
  150 + fn project(&self, _camera :&Camera<T>) -> Vec<Polygon> {
140 fn polygon<I>(c :I) -> Polygon 151 fn polygon<I>(c :I) -> Polygon
141 where I: Iterator<Item = Coordinate> { 152 where I: Iterator<Item = Coordinate> {
142 Polygon(Coordinates(c.collect())) 153 Polygon(Coordinates(c.collect()))
143 } 154 }
144 155
145 - let to_coord = |p :&usize| camera.project(self.points[*p]); 156 + // this one does the projection... as the projection was the last
  157 + // matrix we do not need to do it here.
  158 + // let to_coord = |p :&usize| _camera.project(self.points[*p]);
  159 + let to_coord = |p :&usize| {
  160 + let v = self.points[*p];
  161 + Coordinate(v.x().round(), v.y().round()) };
146 let to_poly = |f :&Vec<usize>| polygon(f.iter().map(to_coord)); 162 let to_poly = |f :&Vec<usize>| polygon(f.iter().map(to_coord));
147 163
148 self.faces.iter().map(to_poly).collect() 164 self.faces.iter().map(to_poly).collect()
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 // 20 //
21 use std::convert::{TryFrom, TryInto, Into}; 21 use std::convert::{TryFrom, TryInto, Into};
22 use std::f64::consts::PI as FPI; 22 use std::f64::consts::PI as FPI;
23 -use std::fmt::Display; 23 +use std::fmt::{Debug, Display};
24 use std::marker::Send; 24 use std::marker::Send;
25 use std::num::TryFromIntError; 25 use std::num::TryFromIntError;
26 use std::ops::{Add,Sub,Neg,Mul,Div}; 26 use std::ops::{Add,Sub,Neg,Mul,Div};
@@ -201,7 +201,7 @@ fn _transform2() { @@ -201,7 +201,7 @@ fn _transform2() {
201 fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>) 201 fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>)
202 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> 202 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
203 + Mul<Output = T> + Div<Output = T> + Trig 203 + Mul<Output = T> + Div<Output = T> + Trig
204 - + From<i32> + Copy + Display { 204 + + Debug + From<i32> + Copy + Display {
205 205
206 println!("{:>14} : {}", "Vector v1", v1); 206 println!("{:>14} : {}", "Vector v1", v1);
207 println!("{:>14} : {}", "translate v1", translate(v).apply(&v1)); 207 println!("{:>14} : {}", "translate v1", translate(v).apply(&v1));
@@ -211,7 +211,7 @@ fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>) @@ -211,7 +211,7 @@ fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>)
211 , fs :&[&dyn Fn(i32) -> TMatrix<T>] ) 211 , fs :&[&dyn Fn(i32) -> TMatrix<T>] )
212 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> 212 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
213 + Mul<Output = T> + Div<Output = T> + Trig 213 + Mul<Output = T> + Div<Output = T> + Trig
214 - + From<i32> + Copy + Display { 214 + + Debug + From<i32> + Copy + Display {
215 215
216 for d in [ 30, 45, 60, 90, 120, 135, 150, 180 216 for d in [ 30, 45, 60, 90, 120, 135, 150, 180
217 , 210, 225, 240, 270, 300, 315, 330 ].iter() { 217 , 210, 225, 240, 270, 300, 315, 330 ].iter() {
@@ -317,7 +317,7 @@ fn _democanvas<T>( xcb :&XcbEasel @@ -317,7 +317,7 @@ fn _democanvas<T>( xcb :&XcbEasel
317 , cube :Polyeder<T> ) 317 , cube :Polyeder<T> )
318 where T: 'static + Add<Output = T> + Sub<Output = T> + Neg<Output = T> 318 where T: 'static + Add<Output = T> + Sub<Output = T> + Neg<Output = T>
319 + Mul<Output = T> + Div<Output = T> 319 + Mul<Output = T> + Div<Output = T>
320 - + Copy + Trig + Send + From<i32> { 320 + + Debug + Copy + Trig + Send + From<i32> {
321 321
322 let mut canvas = xcb.canvas(151, 151).unwrap(); 322 let mut canvas = xcb.canvas(151, 151).unwrap();
323 let camera = Camera::<T>::new(&canvas, 45); // the orig. view angle 323 let camera = Camera::<T>::new(&canvas, 45); // the orig. view angle
@@ -333,14 +333,15 @@ fn _democanvas<T>( xcb :&XcbEasel @@ -333,14 +333,15 @@ fn _democanvas<T>( xcb :&XcbEasel
333 let mut last = Instant::now(); 333 let mut last = Instant::now();
334 334
335 let t :TMatrix<T> = translate(Vector(0.into(), 0.into(), 150.into())); 335 let t :TMatrix<T> = translate(Vector(0.into(), 0.into(), 150.into()));
  336 + let p :TMatrix<T> = camera.get_projection();
336 337
337 loop { 338 loop {
338 let deg = ((start.elapsed() / 25).as_millis() % 360) as i32; 339 let deg = ((start.elapsed() / 25).as_millis() % 360) as i32;
339 340
340 let rz :TMatrix<T> = rotate_z(deg); 341 let rz :TMatrix<T> = rotate_z(deg);
341 342
342 - let rot1 = TMatrix::combine(vec!(rz, rotate_x(-deg*2), t));  
343 - let rot2 = TMatrix::combine(vec!(rz, rotate_y(-deg*2), t)); 343 + let rot1 = TMatrix::combine(vec!(rz, rotate_x(-deg*2), t, p));
  344 + let rot2 = TMatrix::combine(vec!(rz, rotate_y(-deg*2), t, p));
344 345
345 let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) 346 let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00)
346 , ( cube.transform(&rot2), 0x0000FF) ); 347 , ( cube.transform(&rot2), 0x0000FF) );
Please register or login to post a comment