-
-
Save intendednull/40cd183ec0808da8e405a40037760434 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Build a mesh for given polygon. | |
pub fn build_poly(poly: &Poly) -> Mesh { | |
let count = poly.count(); | |
let mut indices = { | |
// Collect all vertices | |
let mut data = poly | |
.iter() | |
.map(|v| std::array::IntoIter::new([v.x as f64, v.z as f64])) | |
.flatten() | |
.collect::<Vec<_>>(); | |
// Add holes | |
let mut hole_indicies = Vec::new(); | |
for hole in &poly.holes { | |
hole_indicies.push(data.len() / 2); | |
data.extend( | |
hole.iter() | |
.map(|v| std::array::IntoIter::new([v.x as f64, v.z as f64])) | |
.flatten(), | |
) | |
} | |
// Triangulate with earcutr | |
let mut out = earcut(&data, &hole_indicies, 2) | |
.into_iter() | |
// Adjust output for bevy | |
.map(|i| i as u32) | |
.rev() | |
.collect::<Vec<_>>(); | |
// Add indicies for drawing bottom | |
let mut bottom = out | |
.iter() | |
.map(|i| i + count as u32) | |
.rev() | |
.collect::<Vec<_>>(); | |
out.append(&mut bottom); | |
out | |
}; | |
let mut vertices = { | |
let vs = poly | |
.iter() | |
.chain(poly.holes.iter().flat_map(|hole| hole.iter())); | |
// Top vertices | |
let mut data = vs | |
.clone() | |
.map(|v| [v.x, v.y + poly.height, v.z]) | |
.collect::<Vec<_>>(); | |
// Bottom vertices | |
data.extend(vs.map(|v| [v.x, v.y, v.z])); | |
data | |
}; | |
let mut normals = { | |
// Normals for top | |
let mut data = vec![[0., 1., 0.]; count]; | |
// Normals for bottom | |
data.extend(std::iter::repeat([0., -1., 0.]).take(count)); | |
data | |
}; | |
// TODO: What should these be? | |
let mut uvs = vec![[0., 0.]; count * 2]; | |
// Draw the sides | |
let mut draw_side = |(v1, v2): (Vec3, Vec3), hole: bool| { | |
let pos = vertices.len() as u32; | |
// Add vertices | |
// IMPORTANT: Order matters! Don't rearrange without updating how they're drawn with | |
// indices below. | |
vertices.push([v1.x, v1.y + poly.height, v1.z]); // Top | |
vertices.push([v1.x, v1.y, v1.z]); // Bottom | |
vertices.push([v2.x, v2.y + poly.height, v2.z]); // Top | |
vertices.push([v2.x, v2.y, v2.z]); // Bottom | |
// Add indices | |
// | |
// If sides are inside a hole, they should face inwards. | |
if hole { | |
indices.push(pos + 3); // v2 bottom | |
indices.push(pos + 1); // v1 bottom | |
indices.push(pos); // v1 top | |
indices.push(pos); // v1 top | |
indices.push(pos + 2); // v2 top | |
indices.push(pos + 3); // v2 bottom | |
normals.extend({ | |
let normal: [f32; 3] = (-(v2 - v1).as_2d().perp().normalize().as_3d()).into(); | |
std::iter::repeat(normal).take(4) | |
}); | |
// Otherwise they should face outwards. | |
} else { | |
indices.push(pos); // v1 top | |
indices.push(pos + 1); // v1 bottom | |
indices.push(pos + 3); // v2 bottom | |
indices.push(pos + 3); // v2 bottom | |
indices.push(pos + 2); // v2 top | |
indices.push(pos); // v1 top | |
normals.extend({ | |
let normal: [f32; 3] = (v2 - v1).as_2d().perp().normalize().as_3d().into(); | |
std::iter::repeat(normal).take(4) | |
}); | |
} | |
// Add uvs | |
uvs.extend(std::iter::repeat([0., 0.]).take(4)); | |
}; | |
for side in poly.borders() { | |
draw_side(side, false); | |
} | |
for hole in poly.holes.iter() { | |
for side in hole.borders() { | |
draw_side(side, true); | |
} | |
} | |
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); | |
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals); | |
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, vertices); | |
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs); | |
mesh.set_indices(Some(Indices::U32(indices))); | |
mesh | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment