makepad_draw/geometry/
geometry_gen.rs

1use {
2    crate::{
3        makepad_derive_live::*,
4        makepad_platform::*,
5    },
6};
7
8live_design!{
9    GeometryQuad2D = {{GeometryQuad2D}} {
10        x1: 0.0;
11        y1: 0.0;
12        x2: 1.0;
13        y2: 1.0;
14    }
15}
16
17impl LiveHook for GeometryQuad2D {
18    fn after_apply(&mut self, cx: &mut Cx, _apply_from:ApplyFrom, _index:usize, _nodes:&[LiveNode]) {
19        let mut fp = GeometryFingerprint::new(LiveType::of::<Self>());
20        fp.push(self.x1);
21        fp.push(self.y1);
22        fp.push(self.x2);
23        fp.push(self.y2);
24        // lets get the fingerprint
25        self.geometry_ref = Some(cx.get_geometry_ref(fp));
26        GeometryGen::from_quad_2d(
27            self.x1,
28            self.y1,
29            self.x2,
30            self.y2,
31        ).to_geometry(cx, &self.geometry_ref.as_ref().unwrap().0);
32    }
33}
34
35impl GeometryFields for GeometryQuad2D {
36    fn geometry_fields(&self, fields: &mut Vec<GeometryField>) {
37        fields.push(GeometryField {id: live_id!(geom_pos), ty: ShaderTy::Vec2});
38    }
39    
40    fn get_geometry_id(&self) -> Option<GeometryId> {
41        // ok so what about doing a Rc<Geometry> based on input and class type
42        if let Some(gr) = &self.geometry_ref{
43            Some(gr.0.geometry_id())
44        }
45        else{
46            None
47        }
48    }
49    
50    fn live_type_check(&self) -> LiveType {
51        LiveType::of::<Self>()
52    }
53}
54
55#[derive(Live)]
56pub struct GeometryQuad2D {
57    #[rust] pub geometry_ref: Option<GeometryRef>,
58    #[live(0.0)] pub x1: f32,
59    #[live(0.0)] pub y1: f32,
60    #[live(1.0)] pub x2: f32,
61    #[live(1.0)] pub y2: f32,
62}
63
64#[derive(Clone, Debug, Default, PartialEq)]
65pub struct GeometryGen {
66    pub vertices: Vec<f32>, // vec4 pos, vec3 normal, vec2 uv
67    pub indices: Vec<u32>
68}
69
70#[derive(Clone, Copy)]
71pub enum GeometryAxis {
72    X = 0,
73    Y = 1,
74    Z = 2,
75}
76
77impl GeometryGen {
78    
79    pub fn to_geometry(self, cx:&mut Cx, geometry:&Geometry){
80        geometry.update(cx, self.indices, self.vertices);
81    }
82    
83    pub fn from_quad_2d(x1: f32, y1: f32, x2: f32, y2: f32) -> GeometryGen {
84        let mut g = Self::default();
85        g.add_quad_2d(x1, y1, x2, y2);
86        g
87    }
88    
89    pub fn from_cube_3d(
90        width: f32,
91        height: f32,
92        depth: f32,
93        width_segments: usize,
94        height_segments: usize,
95        depth_segments: usize
96    ) -> GeometryGen {
97        let mut g = Self::default();
98        g.add_cube_3d(width, height, depth, width_segments, height_segments, depth_segments);
99        g
100    }
101    
102    // requires pos:vec2 normalized layout
103    pub fn add_quad_2d(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
104        let vertex_offset = self.vertices.len() as u32;
105        self.vertices.push(x1);
106        self.vertices.push(y1);
107        self.vertices.push(x2);
108        self.vertices.push(y1);
109        self.vertices.push(x2);
110        self.vertices.push(y2);
111        self.vertices.push(x1);
112        self.vertices.push(y2);
113        self.indices.push(vertex_offset + 0);
114        self.indices.push(vertex_offset + 1);
115        self.indices.push(vertex_offset + 2);
116        self.indices.push(vertex_offset + 2);
117        self.indices.push(vertex_offset + 3);
118        self.indices.push(vertex_offset + 0);
119    }
120    
121    // requires pos:vec3, id:float, normal:vec3, uv:vec2 layout
122    pub fn add_cube_3d(
123        &mut self,
124        width: f32,
125        height: f32,
126        depth: f32,
127        width_segments: usize,
128        height_segments: usize,
129        depth_segments: usize
130    ) {
131        self.add_plane_3d(GeometryAxis::Z, GeometryAxis::Y, GeometryAxis::X, -1.0, -1.0, depth, height, width, depth_segments, height_segments, 0.0);
132        self.add_plane_3d(GeometryAxis::Z, GeometryAxis::Y, GeometryAxis::X, 1.0, -1.0, depth, height, -width, depth_segments, height_segments, 1.0);
133        self.add_plane_3d(GeometryAxis::X, GeometryAxis::Z, GeometryAxis::Y, 1.0, 1.0, width, depth, height, width_segments, depth_segments, 2.0);
134        self.add_plane_3d(GeometryAxis::X, GeometryAxis::Z, GeometryAxis::Y, 1.0, -1.0, width, depth, -height, width_segments, depth_segments, 3.0);
135        self.add_plane_3d(GeometryAxis::X, GeometryAxis::Y, GeometryAxis::Z, 1.0, -1.0, width, height, depth, width_segments, height_segments, 4.0);
136        self.add_plane_3d(GeometryAxis::X, GeometryAxis::Y, GeometryAxis::Z, -1.0, -1.0, width, height, -depth, width_segments, height_segments, 5.0);
137    }
138    
139    
140    // requires pos:vec3, id:float, normal:vec3, uv:vec2 layout
141    pub fn add_plane_3d(
142        &mut self,
143        u: GeometryAxis,
144        v: GeometryAxis,
145        w: GeometryAxis,
146        udir: f32,
147        vdir: f32,
148        width: f32,
149        height: f32,
150        depth: f32,
151        grid_x: usize,
152        grid_y: usize,
153        id: f32
154    ) {
155        let segment_width = width / (grid_x as f32);
156        let segment_height = height / (grid_y as f32);
157        let width_half = width / 2.0;
158        let height_half = height / 2.0;
159        let depth_half = depth / 2.0;
160        let grid_x1 = grid_x + 1;
161        let grid_y1 = grid_y + 1;
162        
163        let vertex_offset = self.vertices.len() / 9;
164        
165        for iy in 0..grid_y1 {
166            let y = (iy as f32) * segment_height - height_half;
167            
168            for ix in 0..grid_x1 {
169                
170                let x = (ix as f32) * segment_width - width_half;
171                let off = self.vertices.len();
172                self.vertices.push(0.0);
173                self.vertices.push(0.0);
174                self.vertices.push(0.0);
175                
176                self.vertices[off + u as usize] = x * udir;
177                self.vertices[off + v as usize] = y * vdir;
178                self.vertices[off + w as usize] = depth_half;
179                
180                self.vertices.push(id);
181                let off = self.vertices.len();
182                self.vertices.push(0.0);
183                self.vertices.push(0.0);
184                self.vertices.push(0.0);
185                self.vertices[off + w as usize] = if depth > 0.0 {1.0} else {-1.0};
186                
187                self.vertices.push((ix as f32) / (grid_x as f32));
188                self.vertices.push(1.0 - (iy as f32) / (grid_y as f32));
189            }
190        }
191        
192        for iy in 0..grid_y {
193            for ix in 0..grid_x {
194                let a = vertex_offset + ix + grid_x1 * iy;
195                let b = vertex_offset + ix + grid_x1 * (iy + 1);
196                let c = vertex_offset + (ix + 1) + grid_x1 * (iy + 1);
197                let d = vertex_offset + (ix + 1) + grid_x1 * iy;
198                self.indices.push(a as u32);
199                self.indices.push(b as u32);
200                self.indices.push(d as u32);
201                self.indices.push(b as u32);
202                self.indices.push(c as u32);
203                self.indices.push(d as u32);
204            }
205        }
206    }
207}