To do: End caps are not being added correctly. I think it's a problem with normals. Need to find way to ensure the circle segments of each ring are rotated so that the sides line up properly.
KBRPBNDCPWA63T2TRQTWWHOHPDXCLSVP7WGPUJKGYJ4RLXNBZBYQC commands.insert_resource(Track {curve: CubicCardinalSpline::new(1.0, curve_points.clone()).to_curve(),points: curve_points,
let track = Track::new(curve_points, 5.0, 16, 200);let mesh = track.mesh();commands.spawn(PbrBundle {mesh: meshes.add(mesh),material: mat.add(StandardMaterial::default()),..default()
points: Vec<Vec3>,
/// The radius of the generated mesh.radius: f32,/// The number of points along the curve to sample/// to generate rings in the mesh.rings: usize,/// The index of the vertex containing the start of each ring.ring_indices: Vec<u32>,/// The number of points in each/// cross-section of the mesh.circle_segments: u32,/// The generated Vec3s for our vertices.vertices: Vec<Vec3>,/// The normal at each vertex.normals: Vec<Vec3>,/// The UV texture coordinates at each vertex.uvs: Vec<[f32; 2]>,/// The vertex indices of the/// triangles making up the mesh.vertex_indices: Vec<u32>,
pub fn draw_test_mesh(mut commands: Commands,mut meshes: ResMut<Assets<Mesh>>,mut mat: ResMut<Assets<StandardMaterial>>,) {let center: [f32; 3] = [0.0, 0.0, -20.0];let radius: f32 = 5.0;let circle_segments: u32 = 16;let mut positions = vec![center];let normals = vec![[0.0, 0.0, 1.0]; circle_segments as usize + 1];let mut vertices: Vec<u32> = vec![];let mut uvs = vec![[0.0, 0.0]];for i in 0..circle_segments + 1 {vertices.push(0);vertices.push(circle_segments);vertices.push(1);if i > 0 {vertices.push(0);vertices.push(i);vertices.push(i + 1);
let mut track = Track {points: points.clone(),curve: CubicCardinalSpline::new(0.5, points).to_curve(),radius,rings,ring_indices: vec![],circle_segments,vertices: vec![center],normals: vec![Vec3::new(0.0, 0.0, 1.0); circle_segments as usize + 1],uvs: vec![[0.0, 0.0]],vertex_indices: vec![],};for t in 0..track.rings {track.add_ring(track.points.len() as f32 * t as f32 / track.rings as f32);if t == 0 || t == track.rings - 1 {let center_index = track.vertices.len() as u32;track.uvs.push([0.0, 0.0]);track.vertices.push(track.curve.position(t as f32 / track.rings as f32));track.add_cap(center_index, track.ring_indices[t]);}if t > 0 {track.add_sides(track.ring_indices[t - 1], track.ring_indices[t]);}}track}/// Add the cap to the an end of the mesh.fn add_cap(&mut self, center_index: u32, ring_index: u32) {for i in 0..self.circle_segments - 1 {self.vertex_indices.push(center_index);self.vertex_indices.push(ring_index + i);self.vertex_indices.push(ring_index + i + 1);
let angle = i as f32 * 2.0 * PI / circle_segments as f32;
/// Draw the quads connecting two rings in our mesh/// first ring/// a--b first_segment/// | |/// | |/// c--d next segment/// next ringfn add_sides(&mut self, first_ring: u32, next_ring: u32) {for i in 0..self.circle_segments - 1 {let a = first_ring + i;let b = next_ring + i;let c = first_ring + i + 1;let d = next_ring + i + 1;self.vertex_indices.extend([c, d, a, a, d, b].into_iter());}let a = first_ring + self.circle_segments - 1;let b = next_ring + self.circle_segments - 1;let c = first_ring;let d = next_ring;self.vertex_indices.extend([c, d, a, a, d, b].into_iter());}fn add_ring(&mut self, t: f32) {self.ring_indices.push(self.vertices.len() as u32);
let x = angle.cos();let y = angle.sin();
let center = self.curve.position(t);let forward = self.curve.velocity(t).normalize();let mut up = Vec3::new(0.0, 1.0, 0.0);if up.dot(forward) > 0.9 {up = Vec3::new(1.0, 0.0, 0.0);}let right = up.cross(forward);
positions.push([center[0] + x * radius,center[1] + y * radius,center[2] + 0.0,]);//uvs.push([0.5 * (x * 0.5), -0.5 + (y * 0.5)]);uvs.push([0.0, 0.0]);
for i in 0..self.circle_segments + 1 {let angle = i as f32 * 2.0 * PI / self.circle_segments as f32;let x = angle.cos();let y = angle.sin();self.vertices.push(center + right * x + up * y);self.uvs.push([0.0, 0.0]);}}fn mesh(&self) -> Mesh {let mut mesh = Mesh::new(PrimitiveTopology::TriangleList,RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,).with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, self.vertices.clone()).with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, self.uvs.clone()).with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, self.normals.clone()).with_inserted_indices(Indices::U32(self.vertex_indices.clone()));mesh.compute_normals();mesh
let mesh = Mesh::new(PrimitiveTopology::TriangleList,RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,).with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions).with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs).with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals).with_inserted_indices(Indices::U32(vertices));commands.spawn(PbrBundle {mesh: meshes.add(mesh),material: mat.add(StandardMaterial::default()),..default()});