1
- use nalgebra:: Matrix4 ;
2
1
use crate :: base:: SimpleMesh ;
3
- use std:: { f32} ;
2
+ use crossterm:: { cursor, terminal, Attribute , Color , Colored } ;
3
+ use nalgebra:: Matrix4 ;
4
+ use std:: error:: Error ;
5
+ use std:: f32;
4
6
5
7
pub struct Context {
6
8
pub utransform : Matrix4 < f32 > ,
7
9
pub width : usize ,
8
10
pub height : usize ,
9
- pub frame_buffer : Vec < String > ,
11
+ pub frame_buffer : Vec < ( char , ( u8 , u8 , u8 ) ) > ,
10
12
pub z_buffer : Vec < f32 > ,
11
13
}
12
14
@@ -15,39 +17,73 @@ impl Context {
15
17
//TODO: Make this a constant struct
16
18
Context {
17
19
utransform : Matrix4 :: new (
18
- 1.0 , 0.0 , 0.0 , 0.0 ,
19
- 0.0 , 1.0 , 0.0 , 0.0 ,
20
- 0.0 , 0.0 , 1.0 , 0.0 ,
21
- 0.0 , 0.0 , 0.0 , 1.0 ,
20
+ 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ,
22
21
) ,
23
22
width : 0 ,
24
23
height : 0 ,
25
24
frame_buffer : vec ! [ ] ,
26
- z_buffer : vec ! [ ]
25
+ z_buffer : vec ! [ ] ,
27
26
}
28
27
}
29
28
pub fn clear ( & mut self ) {
30
- self . frame_buffer = vec ! [ " " . to_string ( ) ; self . width * self . height as usize ] ;
29
+ self . frame_buffer = vec ! [ ( ' ' , ( 0 , 0 , 0 ) ) ; self . width * self . height as usize ] ;
31
30
self . z_buffer = vec ! [ f32 :: MAX ; self . width * self . height as usize ] ; //f32::MAX is written to the z-buffer as an infinite back-wall to render with
32
31
}
33
32
pub fn camera ( & mut self , proj : Matrix4 < f32 > , view : Matrix4 < f32 > ) -> & Matrix4 < f32 > {
34
33
self . utransform = proj * view;
35
34
& self . utransform
36
35
}
37
- pub fn flush ( & self ) {
38
- let mut x: String = "" . to_string ( ) ;
36
+ pub fn flush ( & self ) -> Result < ( ) , Box < Error > > {
37
+ let cursor = cursor ( ) ;
38
+ cursor. goto ( 0 , 0 ) ?;
39
+
40
+ let mut prev_color = None ;
41
+
39
42
for pixel in & self . frame_buffer {
40
- x. push_str ( pixel) ;
43
+ match prev_color {
44
+ Some ( c) if c == pixel. 1 => {
45
+ print ! ( "{}" , pixel. 0 ) ;
46
+ }
47
+ _ => {
48
+ prev_color = Some ( pixel. 1 ) ;
49
+ print ! (
50
+ "{}{}{}" ,
51
+ Colored :: Fg ( Color :: Rgb {
52
+ r: ( pixel. 1 ) . 0 ,
53
+ g: ( pixel. 1 ) . 1 ,
54
+ b: ( pixel. 1 ) . 2
55
+ } ) ,
56
+ Colored :: Bg ( Color :: Rgb {
57
+ r: 25 ,
58
+ g: 25 ,
59
+ b: 25
60
+ } ) ,
61
+ pixel. 0
62
+ )
63
+ }
64
+ }
41
65
}
42
- println ! ( "{}{}{}" , termion:: clear:: All , termion:: cursor:: Goto ( 1 , 1 ) , x) ;
66
+
67
+ println ! ( "{}" , Attribute :: Reset ) ;
68
+
69
+ Ok ( ( ) )
43
70
}
44
- pub fn update ( & mut self , mut old_size : ( u16 , u16 ) ,
71
+ pub fn update (
72
+ & mut self ,
73
+ mut old_size : ( u16 , u16 ) ,
45
74
meshes : & [ SimpleMesh ] ,
46
- ) {
47
- let terminal_size = termion:: terminal_size ( ) . unwrap ( ) ; // Temporary size
75
+ ) -> Result < ( ) , Box < Error > > {
76
+ let terminal = terminal ( ) ;
77
+ let terminal_size = terminal. terminal_size ( ) ;
78
+
48
79
if old_size != terminal_size {
49
80
// Check if the size changed
81
+ let cursor = cursor ( ) ;
82
+
83
+ //re-hide the cursor
84
+ cursor. hide ( ) ?;
50
85
old_size = terminal_size; // It changed! Set new size
86
+ old_size. 0 += 1 ;
51
87
let mut scale: f32 = 0.0 ; // The scene's scale
52
88
for mesh in meshes {
53
89
// This calculates the maximum axis value (x y or z) in all meshes
@@ -57,14 +93,29 @@ impl Context {
57
93
. max ( mesh. bounding_box . max . z ) ;
58
94
}
59
95
scale = f32:: from ( old_size. 1 ) . min ( f32:: from ( old_size. 0 ) / 2.0 ) / scale / 2.0 ; // Constrain to width and height, whichever is smaller
60
- let t = Matrix4 :: new ( scale, 0.0 , 0.0 , f32:: from ( old_size. 0 ) / 4.0 , // X translation is divided by 4 because there's a 1 char space between charxels
61
- 0.0 , -scale, 0.0 , f32:: from ( old_size. 1 ) / 2.0 , // Y translation is divided by 2 to center
62
- 0.0 , 0.0 , scale, 0.0 ,
63
- 0.0 , 0.0 , 0.0 , 1.0 ,
96
+ let t = Matrix4 :: new (
97
+ scale,
98
+ 0.0 ,
99
+ 0.0 ,
100
+ f32:: from ( old_size. 0 ) / 4.0 , // X translation is divided by 4 because there's a 1 char space between charxels
101
+ 0.0 ,
102
+ -scale,
103
+ 0.0 ,
104
+ f32:: from ( old_size. 1 ) / 2.0 , // Y translation is divided by 2 to center
105
+ 0.0 ,
106
+ 0.0 ,
107
+ scale,
108
+ 0.0 ,
109
+ 0.0 ,
110
+ 0.0 ,
111
+ 0.0 ,
112
+ 1.0 ,
64
113
) ;
65
114
self . utransform = t;
66
- self . width = ( old_size. 0 ) as usize ;
67
- self . height = ( old_size. 1 - 1 ) as usize ;
115
+ self . width = old_size. 0 as usize ;
116
+ self . height = ( old_size. 1 ) as usize ;
68
117
}
118
+
119
+ Ok ( ( ) )
69
120
}
70
121
}
0 commit comments