mesh_generation/mesh/
polymesh.rs

1use nalgebra::base::{Vector3, Vector2};
2use std::fs::File;
3use std::io::prelude::*;
4
5pub struct PolyMesh {
6    pub num_vertices: u32,
7    pub vertices: Vec<Vector3<f64>>, 
8    pub vertices_array: Vec<u32>,
9    pub st: Vec<Vector2<f64>>,
10    pub normals: Vec<Vector3<f64>>,
11    pub num_faces: u32,
12    pub face_array: Vec<u32>,
13}
14
15const DEFAULT_WIDTH: u32 = 40;
16const DEFAULT_HEIGHT: u32 = 40;
17
18impl PolyMesh {
19
20    /// Creates new mesh with `subdivision_width` and `subdivision_height` subdivisions width wise and height wise respectively.
21    /// Height and width set the scale of the mesh.
22    pub fn new(
23        subdivision_width: Option<u32>, 
24        subdivision_height: Option<u32>,
25        height: Option<u32>,
26        width: Option<u32>,
27    ) -> Self {
28        let subdivision_width = subdivision_width.unwrap_or(DEFAULT_WIDTH);
29        let subdivision_height = subdivision_height.unwrap_or(DEFAULT_HEIGHT);
30
31        let num_vertices = (subdivision_width + 1) * (subdivision_height + 1);
32        let vertices = vec![Vector3::<f64>::new(0.0, 0.0, 0.0); num_vertices as usize];
33        let st = vec![Vector2::<f64>::new(0.0, 0.0); num_vertices as usize];
34        let num_faces = subdivision_width * subdivision_height; 
35        let face_array = vec![4 as u32; num_faces as usize];
36        let vertices_array = vec![0 as u32; 4*num_faces as usize];
37        let normals = vec![Vector3::<f64>::new(0.0, 1.0, 0.0); num_vertices as usize];
38        println!("Vertices: {} Faces: {}", num_vertices, num_faces);
39        // Empty mesh
40        let mut mesh = PolyMesh {
41            num_vertices,
42            vertices,
43            vertices_array,
44            st,
45            normals,
46            num_faces,
47            face_array,
48        };
49
50        // Base flat mesh
51        let height = height.unwrap_or(1) as f64;
52        let width = width.unwrap_or(1) as f64;
53        let invsubdivision_width = 1.0 / subdivision_width as f64; 
54        let invsubdivision_height = 1.0 / subdivision_height as f64;
55        println!("Height: {} Inverse: {} Width:{} Inverse:{}", subdivision_height, invsubdivision_height, subdivision_width, invsubdivision_width);
56        for j in 0..(subdivision_height+1) {
57            for i in 0..(subdivision_width+1) {
58                mesh.vertices[(j * (subdivision_width + 1) + i) as usize] = Vector3::<f64>::new(width * (i as f64 * invsubdivision_width - 0.5), 0.0, height * (j as f64 * invsubdivision_height - 0.5));
59                mesh.st[(j * (subdivision_width + 1) + i) as usize] = Vector2::<f64>::new(i as f64 * invsubdivision_width, j as f64 * invsubdivision_height);
60            }
61        }
62
63        let mut k = 0;
64        for j in 0..subdivision_height { 
65            for i in 0..subdivision_height { 
66                mesh.vertices_array[k] = j * (subdivision_width + 1) + i; 
67                mesh.vertices_array[k + 1] = j * (subdivision_width + 1) + i + 1; 
68                mesh.vertices_array[k + 2] = (j + 1) * (subdivision_width + 1) + i + 1; 
69                mesh.vertices_array[k + 3] = (j + 1) * (subdivision_width + 1) + i; 
70                k += 4; 
71            } 
72        } 
73        mesh
74    }
75
76    /// Exports mesh to obj format
77    pub fn export_to_obj(&self, filename: &str) {
78        let file_handle = File::create(filename);
79        if let Ok(mut file) = file_handle {
80            for i in 0..self.num_vertices {
81                file.write_all(format!("v {} {} {}\n", self.vertices[i as usize].x, self.vertices[i as usize].y, self.vertices[i as usize].z).as_bytes()).expect("write failed");
82            }
83            for i in 0..self.num_vertices {
84                file.write_all(format!("vt {} {}\n", self.st[i as usize].x, self.st[i as usize].y).as_bytes()).expect("write failed");
85            }
86            for i in 0..self.num_vertices {
87                file.write_all(format!("vn {} {} {}\n", self.normals[i as usize].x, self.normals[i as usize].y, self.normals[i as usize].z).as_bytes()).expect("write failed");
88            }
89            let mut k:u32 = 0;
90            for i in 0..self.num_faces {
91                file.write_all(b"f ").expect("write failed");
92                for j in 0..self.face_array[i as usize] {
93                    let obj_index: u32 = self.vertices_array[(k + j) as usize] + 1;
94                    let end = if j == (self.face_array[i as usize] -1) { "" } else {" "};
95                    file.write_all(format!("{}/{}/{}{}", obj_index, obj_index, obj_index, end).as_bytes()).expect("write failed");
96                }
97                file.write_all(b"\n").expect("write failed");
98                k+=self.face_array[i as usize];
99            }
100        }
101    }
102
103    /// Calculates normals using geometric normals
104    pub fn calculate_normals(&mut self) {
105        let mut off: usize = 0;
106        for k in 0..self.num_faces {
107            let nverts = self.face_array[k as usize] as usize;
108            let vector_a = self.vertices[(self.vertices_array[off]) as usize];
109            let vector_b = self.vertices[(self.vertices_array[off+ 1]) as usize];
110            let vector_c = self.vertices[(self.vertices_array[off + nverts - 1]) as usize];
111    
112            let tangent = vector_b - vector_a; 
113            let bitangent = vector_c - vector_a;
114    
115            self.normals[self.vertices_array[off] as usize]  = bitangent.cross(&tangent).normalize();
116            off += nverts;
117        }
118    }
119    
120    /// Displaces mesh according to noise map provided.
121    pub fn displace_with_noise_map(&mut self, noise_map: Vec<f64>, image_width: u32, image_height: u32) {
122        let image_width = image_width as f64;
123        let image_height = image_height as f64;
124        for i in  0..self.num_vertices { 
125            let st = self.st[i as usize]; 
126            let x = min(st.x * image_width, image_width - 1.0); 
127            let y = min(st.y * image_height, image_height - 1.0); 
128            self.vertices[i as usize].y = 2.0 * noise_map[(y * image_width + x) as usize] - 1.0; 
129        }
130    }
131}
132
133fn min(a: f64, b: f64) -> f64 {
134    if b < a {
135        b
136    } else  {
137        a
138    }
139}