1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use crate::*; pub struct Edges { program: core::Program, translation_buffer: VertexBuffer, direction_buffer: VertexBuffer, cylinder_index_buffer: core::ElementBuffer, cylinder_vertex_buffer: VertexBuffer, index_pairs: std::collections::HashSet<(usize, usize)>, no_edges: u32, tube_radius: f32, pub color: Vec3, pub diffuse_intensity: f32, pub specular_intensity: f32, pub specular_power: f32 } impl Edges { pub fn new(gl: &Gl, indices: &[u32], positions: &[f32], tube_radius: f32) -> Edges { let program = core::Program::from_source(&gl, include_str!("shaders/line_shaded.vert"), include_str!("shaders/shaded.frag")).unwrap(); let x_subdivisions = 1; let angle_subdivisions = 10; let mut cylinder_positions = Vec::new(); let mut cylinder_indices = Vec::new(); for i in 0..x_subdivisions+1 { let x = i as f32 / x_subdivisions as f32; for j in 0..angle_subdivisions { let angle = 2.0 * std::f32::consts::PI * j as f32 / angle_subdivisions as f32; cylinder_positions.push(x); cylinder_positions.push(angle.cos()); cylinder_positions.push(angle.sin()); } } for i in 0..x_subdivisions as u32 { for j in 0..angle_subdivisions as u32 { cylinder_indices.push(i * angle_subdivisions as u32 + j); cylinder_indices.push(i * angle_subdivisions as u32 + (j+1)%angle_subdivisions as u32); cylinder_indices.push((i+1) * angle_subdivisions as u32 + (j+1)%angle_subdivisions as u32); cylinder_indices.push(i * angle_subdivisions as u32 + j); cylinder_indices.push((i+1) * angle_subdivisions as u32 + (j+1)%angle_subdivisions as u32); cylinder_indices.push((i+1) * angle_subdivisions as u32 + j); } } let cylinder_index_buffer = ElementBuffer::new_with_u32(gl, &cylinder_indices).unwrap(); let cylinder_vertex_buffer = VertexBuffer::new_with_static_f32(gl,&cylinder_positions).unwrap(); let mut index_pairs = std::collections::HashSet::new(); for f in 0..indices.len()/3 { let i1 = indices[3*f] as usize; let i2 = indices[3*f+1] as usize; let i3 = indices[3*f+2] as usize; index_pairs.insert(if i1 < i2 {(i1, i2)} else {(i2, i1)}); index_pairs.insert(if i1 < i3 {(i1, i3)} else {(i3, i1)}); index_pairs.insert(if i2 < i3 {(i2, i3)} else {(i3, i2)}); } let no_edges = index_pairs.len() as u32; let (translation, direction) = Self::fill_translation_and_direction(&index_pairs, positions); let translation_buffer = VertexBuffer::new_with_dynamic_f32(gl, &translation).unwrap(); let direction_buffer = VertexBuffer::new_with_dynamic_f32(gl, &direction).unwrap(); Edges { program, translation_buffer, direction_buffer, cylinder_vertex_buffer, cylinder_index_buffer, index_pairs, no_edges, tube_radius, color: vec3(1.0, 0.0, 0.0), diffuse_intensity: 0.5, specular_intensity: 0.2, specular_power: 5.0 } } fn fill_translation_and_direction(index_pairs: &std::collections::HashSet<(usize, usize)>, positions: &[f32]) -> (Vec<f32>, Vec<f32>) { let mut translation = Vec::new(); let mut direction = Vec::new(); for (i0, i1) in index_pairs.iter() { for i in 0..3 { translation.push(positions[i0 * 3 + i]); direction.push(positions[i1 * 3 + i] - positions[i0 * 3 + i]); } } (translation, direction) } pub fn update_positions(&mut self, positions: &[f32]) { let (translation, direction) = Self::fill_translation_and_direction(&self.index_pairs, positions); self.translation_buffer.fill_with_dynamic_f32(&translation); self.direction_buffer.fill_with_dynamic_f32(&direction); } pub fn render(&self, transformation: &Mat4, camera: &camera::Camera) { self.program.add_uniform_float("diffuse_intensity", &self.diffuse_intensity).unwrap(); self.program.add_uniform_float("specular_intensity", &self.specular_intensity).unwrap(); self.program.add_uniform_float("specular_power", &self.specular_power).unwrap(); self.program.add_uniform_int("use_texture", &0).unwrap(); self.program.add_uniform_vec3("color", &self.color).unwrap(); self.program.use_uniform_block(camera.matrix_buffer(), "Camera"); self.program.add_uniform_float("tube_radius", &self.tube_radius).unwrap(); self.program.add_uniform_mat4("modelMatrix", &transformation).unwrap(); self.program.use_attribute_vec3_float_divisor(&self.translation_buffer, "translation", 1).unwrap(); self.program.use_attribute_vec3_float_divisor(&self.direction_buffer, "direction", 1).unwrap(); self.program.use_attribute_vec3_float(&self.cylinder_vertex_buffer, "position").unwrap(); self.program.draw_elements_instanced(&self.cylinder_index_buffer,self.no_edges); } }