terminology: remove uses of the word "mesh". Prefer "triangles".

This commit is contained in:
Emil Ernerfeldt 2020-05-19 20:54:02 +02:00
parent 3ec552392f
commit aeaa611005
8 changed files with 141 additions and 135 deletions

View file

@ -98,7 +98,7 @@ Add extremely quick animations for some things, maybe 2-3 frames. For instance:
* [x] Combine Emigui and Context?
* [x] Solve which parts of Context are behind a mutex
* [x] Rename Region to Ui
* [ ] Move Path and Mesh to own crate
* [ ] Move Path and Triangles to own crate
* [ ] Maybe find a shorter name for the library like `egui`?
### Global widget search

View file

@ -19,7 +19,7 @@ struct PaintStats {
pub struct Context {
/// The default style for new `Ui`:s
style: Mutex<Style>,
mesher_options: Mutex<mesher::MesherOptions>,
paint_options: Mutex<mesher::PaintOptions>,
fonts: Arc<Fonts>,
/// HACK: set a new font next frame
new_fonts: Mutex<Option<Arc<Fonts>>>,
@ -45,7 +45,7 @@ impl Clone for Context {
fn clone(&self) -> Self {
Context {
style: Mutex::new(self.style()),
mesher_options: Mutex::new(*self.mesher_options.lock()),
paint_options: Mutex::new(*self.paint_options.lock()),
fonts: self.fonts.clone(),
new_fonts: Mutex::new(self.new_fonts.lock().clone()),
memory: self.memory.clone(),
@ -65,7 +65,7 @@ impl Context {
pub fn new(pixels_per_point: f32) -> Arc<Context> {
Arc::new(Context {
style: Default::default(),
mesher_options: Default::default(),
paint_options: Default::default(),
fonts: Arc::new(Fonts::new(pixels_per_point)),
new_fonts: Default::default(),
memory: Default::default(),
@ -214,20 +214,21 @@ impl Context {
}
fn paint(&self) -> PaintBatches {
let mut mesher_options = *self.mesher_options.lock();
mesher_options.aa_size = 1.0 / self.pixels_per_point();
mesher_options.aa_size *= 1.5; // Looks better, but TODO: should not be needed
let mut paint_options = *self.paint_options.lock();
paint_options.aa_size = 1.0 / self.pixels_per_point();
paint_options.aa_size *= 1.5; // Looks better, but TODO: should not be needed
let paint_commands = self.drain_paint_lists();
let num_primitives = paint_commands.len();
let batches = mesher::mesh_paint_commands(mesher_options, self.fonts(), paint_commands);
let batches =
mesher::paint_commands_into_triangles(paint_options, self.fonts(), paint_commands);
{
let mut stats = PaintStats::default();
stats.num_batches = batches.len();
stats.num_primitives = num_primitives;
for (_, mesh) in &batches {
stats.num_vertices += mesh.vertices.len();
stats.num_triangles += mesh.indices.len() / 3;
for (_, triangles) in &batches {
stats.num_vertices += triangles.vertices.len();
stats.num_triangles += triangles.indices.len() / 3;
}
*self.paint_stats.lock() = stats;
}
@ -477,7 +478,7 @@ impl Context {
CollapsingHeader::new("Style")
// .default_open()
.show(ui, |ui| {
self.mesher_options.lock().ui(ui);
self.paint_options.lock().ui(ui);
self.style_ui(ui);
});
@ -603,7 +604,7 @@ impl Context {
}
}
impl mesher::MesherOptions {
impl mesher::PaintOptions {
pub fn ui(&mut self, ui: &mut Ui) {
use crate::widgets::*;
ui.add(Checkbox::new(&mut self.anti_alias, "Antialias"));

View file

@ -52,7 +52,7 @@ pub use {
layout::*,
math::*,
memory::Memory,
mesher::{Mesh, PaintBatches, Vertex},
mesher::{PaintBatches, Triangles, Vertex},
movement_tracker::MovementTracker,
style::Style,
texture_atlas::Texture,

View file

@ -22,24 +22,24 @@ pub struct Vertex {
}
#[derive(Clone, Debug, Default, serde_derive::Serialize)]
pub struct Mesh {
pub struct Triangles {
/// Draw as triangles (i.e. the length is a multiple of three)
pub indices: Vec<u32>,
pub vertices: Vec<Vertex>,
}
/// Grouped by clip rectangles, in pixel coordinates
pub type PaintBatches = Vec<(Rect, Mesh)>;
pub type PaintBatches = Vec<(Rect, Triangles)>;
// ----------------------------------------------------------------------------
impl Mesh {
pub fn append(&mut self, mesh: &Mesh) {
impl Triangles {
pub fn append(&mut self, triangles: &Triangles) {
let index_offset = self.vertices.len() as u32;
for index in &mesh.indices {
for index in &triangles.indices {
self.indices.push(index_offset + index);
}
self.vertices.extend(mesh.vertices.iter());
self.vertices.extend(triangles.vertices.iter());
}
fn triangle(&mut self, a: u32, b: u32, c: u32) {
@ -72,9 +72,10 @@ impl Mesh {
self.vertices.push(bottom_right);
}
/// Split a large mesh into many small.
/// All the returned meshes will have indices that fit into u16.
pub fn split_to_u16(self) -> Vec<Mesh> {
/// This is for platsform that only support 16-bit index buffers.
/// Splits this mesh into many small if needed.
/// All the returned meshes will have indices that fit into a `u16`.
pub fn split_to_u16(self) -> Vec<Triangles> {
const MAX_SIZE: u32 = 1 << 16;
if self.vertices.len() < MAX_SIZE as usize {
@ -113,7 +114,7 @@ impl Mesh {
MAX_SIZE
);
output.push(Mesh {
output.push(Triangles {
indices: self.indices[span_start..index_cursor]
.iter()
.map(|vi| vi - min_vindex)
@ -276,14 +277,14 @@ pub enum PathType {
use self::PathType::{Closed, Open};
#[derive(Clone, Copy)]
pub struct MesherOptions {
pub struct PaintOptions {
pub anti_alias: bool,
/// Size of a pixel in points, e.g. 0.5
pub aa_size: f32,
pub debug_paint_clip_rects: bool,
}
impl Default for MesherOptions {
impl Default for PaintOptions {
fn default() -> Self {
Self {
anti_alias: true,
@ -293,7 +294,12 @@ impl Default for MesherOptions {
}
}
pub fn fill_closed_path(mesh: &mut Mesh, options: MesherOptions, path: &[PathPoint], color: Color) {
pub fn fill_closed_path(
triangles: &mut Triangles,
options: PaintOptions,
path: &[PathPoint],
color: Color,
) {
if color == color::TRANSPARENT {
return;
}
@ -306,34 +312,35 @@ pub fn fill_closed_path(mesh: &mut Mesh, options: MesherOptions, path: &[PathPoi
};
if options.anti_alias {
let color_outer = color::TRANSPARENT;
let idx_inner = mesh.vertices.len() as u32;
let idx_inner = triangles.vertices.len() as u32;
let idx_outer = idx_inner + 1;
for i in 2..n {
mesh.triangle(idx_inner + 2 * (i - 1), idx_inner, idx_inner + 2 * i);
triangles.triangle(idx_inner + 2 * (i - 1), idx_inner, idx_inner + 2 * i);
}
let mut i0 = n - 1;
for i1 in 0..n {
let p1 = &path[i1 as usize];
let dm = p1.normal * options.aa_size * 0.5;
mesh.vertices.push(vert(p1.pos - dm, color));
mesh.vertices.push(vert(p1.pos + dm, color_outer));
mesh.triangle(idx_inner + i1 * 2, idx_inner + i0 * 2, idx_outer + 2 * i0);
mesh.triangle(idx_outer + i0 * 2, idx_outer + i1 * 2, idx_inner + 2 * i1);
triangles.vertices.push(vert(p1.pos - dm, color));
triangles.vertices.push(vert(p1.pos + dm, color_outer));
triangles.triangle(idx_inner + i1 * 2, idx_inner + i0 * 2, idx_outer + 2 * i0);
triangles.triangle(idx_outer + i0 * 2, idx_outer + i1 * 2, idx_inner + 2 * i1);
i0 = i1;
}
} else {
let idx = mesh.vertices.len() as u32;
mesh.vertices
let idx = triangles.vertices.len() as u32;
triangles
.vertices
.extend(path.iter().map(|p| vert(p.pos, color)));
for i in 2..n {
mesh.triangle(idx, idx + i - 1, idx + i);
triangles.triangle(idx, idx + i - 1, idx + i);
}
}
}
pub fn paint_path(
mesh: &mut Mesh,
options: MesherOptions,
triangles: &mut Triangles,
options: PaintOptions,
path_type: PathType,
path: &[PathPoint],
color: Color,
@ -344,7 +351,7 @@ pub fn paint_path(
}
let n = path.len() as u32;
let idx = mesh.vertices.len() as u32;
let idx = triangles.vertices.len() as u32;
let vert = |pos, color| Vertex {
pos,
@ -377,18 +384,20 @@ pub fn paint_path(
let p1 = &path[i1 as usize];
let p = p1.pos;
let n = p1.normal;
mesh.vertices
triangles
.vertices
.push(vert(p + n * options.aa_size, color_outer));
mesh.vertices.push(vert(p, color_inner));
mesh.vertices
triangles.vertices.push(vert(p, color_inner));
triangles
.vertices
.push(vert(p - n * options.aa_size, color_outer));
if connect_with_previous {
mesh.triangle(idx + 3 * i0 + 0, idx + 3 * i0 + 1, idx + 3 * i1 + 0);
mesh.triangle(idx + 3 * i0 + 1, idx + 3 * i1 + 0, idx + 3 * i1 + 1);
triangles.triangle(idx + 3 * i0 + 0, idx + 3 * i0 + 1, idx + 3 * i1 + 0);
triangles.triangle(idx + 3 * i0 + 1, idx + 3 * i1 + 0, idx + 3 * i1 + 1);
mesh.triangle(idx + 3 * i0 + 1, idx + 3 * i0 + 2, idx + 3 * i1 + 1);
mesh.triangle(idx + 3 * i0 + 2, idx + 3 * i1 + 1, idx + 3 * i1 + 2);
triangles.triangle(idx + 3 * i0 + 1, idx + 3 * i0 + 2, idx + 3 * i1 + 1);
triangles.triangle(idx + 3 * i0 + 2, idx + 3 * i1 + 1, idx + 3 * i1 + 2);
}
i0 = i1;
}
@ -413,20 +422,28 @@ pub fn paint_path(
let p1 = &path[i1 as usize];
let p = p1.pos;
let n = p1.normal;
mesh.vertices.push(vert(p + n * outer_rad, color_outer));
mesh.vertices.push(vert(p + n * inner_rad, color_inner));
mesh.vertices.push(vert(p - n * inner_rad, color_inner));
mesh.vertices.push(vert(p - n * outer_rad, color_outer));
triangles
.vertices
.push(vert(p + n * outer_rad, color_outer));
triangles
.vertices
.push(vert(p + n * inner_rad, color_inner));
triangles
.vertices
.push(vert(p - n * inner_rad, color_inner));
triangles
.vertices
.push(vert(p - n * outer_rad, color_outer));
if connect_with_previous {
mesh.triangle(idx + 4 * i0 + 0, idx + 4 * i0 + 1, idx + 4 * i1 + 0);
mesh.triangle(idx + 4 * i0 + 1, idx + 4 * i1 + 0, idx + 4 * i1 + 1);
triangles.triangle(idx + 4 * i0 + 0, idx + 4 * i0 + 1, idx + 4 * i1 + 0);
triangles.triangle(idx + 4 * i0 + 1, idx + 4 * i1 + 0, idx + 4 * i1 + 1);
mesh.triangle(idx + 4 * i0 + 1, idx + 4 * i0 + 2, idx + 4 * i1 + 1);
mesh.triangle(idx + 4 * i0 + 2, idx + 4 * i1 + 1, idx + 4 * i1 + 2);
triangles.triangle(idx + 4 * i0 + 1, idx + 4 * i0 + 2, idx + 4 * i1 + 1);
triangles.triangle(idx + 4 * i0 + 2, idx + 4 * i1 + 1, idx + 4 * i1 + 2);
mesh.triangle(idx + 4 * i0 + 2, idx + 4 * i0 + 3, idx + 4 * i1 + 2);
mesh.triangle(idx + 4 * i0 + 3, idx + 4 * i1 + 2, idx + 4 * i1 + 3);
triangles.triangle(idx + 4 * i0 + 2, idx + 4 * i0 + 3, idx + 4 * i1 + 2);
triangles.triangle(idx + 4 * i0 + 3, idx + 4 * i1 + 2, idx + 4 * i1 + 3);
}
i0 = i1;
}
@ -434,12 +451,12 @@ pub fn paint_path(
} else {
let last_index = if path_type == Closed { n } else { n - 1 };
for i in 0..last_index {
mesh.triangle(
triangles.triangle(
idx + (2 * i + 0) % (2 * n),
idx + (2 * i + 1) % (2 * n),
idx + (2 * i + 2) % (2 * n),
);
mesh.triangle(
triangles.triangle(
idx + (2 * i + 2) % (2 * n),
idx + (2 * i + 1) % (2 * n),
idx + (2 * i + 3) % (2 * n),
@ -455,14 +472,22 @@ pub fn paint_path(
return;
}
for p in path {
mesh.vertices.push(vert(p.pos + radius * p.normal, color));
mesh.vertices.push(vert(p.pos - radius * p.normal, color));
triangles
.vertices
.push(vert(p.pos + radius * p.normal, color));
triangles
.vertices
.push(vert(p.pos - radius * p.normal, color));
}
} else {
let radius = width / 2.0;
for p in path {
mesh.vertices.push(vert(p.pos + radius * p.normal, color));
mesh.vertices.push(vert(p.pos - radius * p.normal, color));
triangles
.vertices
.push(vert(p.pos + radius * p.normal, color));
triangles
.vertices
.push(vert(p.pos - radius * p.normal, color));
}
}
}
@ -481,14 +506,15 @@ fn mul_color(color: Color, factor: f32) -> Color {
// ----------------------------------------------------------------------------
/// path: only used to reuse memory
pub fn mesh_command(
path: &mut Path,
options: MesherOptions,
/// `reused_path`: only used to reuse memory
pub fn paint_command_into_triangles(
reused_path: &mut Path,
options: PaintOptions,
fonts: &Fonts,
command: PaintCmd,
out_mesh: &mut Mesh,
out: &mut Triangles,
) {
let path = reused_path;
path.clear();
match command {
@ -500,21 +526,14 @@ pub fn mesh_command(
} => {
path.add_circle(center, radius);
if let Some(color) = fill_color {
fill_closed_path(out_mesh, options, &path.0, color);
fill_closed_path(out, options, &path.0, color);
}
if let Some(outline) = outline {
paint_path(
out_mesh,
options,
Closed,
&path.0,
outline.color,
outline.width,
);
paint_path(out, options, Closed, &path.0, outline.color, outline.width);
}
}
PaintCmd::Mesh(mesh) => {
out_mesh.append(&mesh);
PaintCmd::Triangles(triangles) => {
out.append(&triangles);
}
PaintCmd::LineSegment {
points,
@ -522,7 +541,7 @@ pub fn mesh_command(
width,
} => {
path.add_line_segment(points);
paint_path(out_mesh, options, Open, &path.0, color, width);
paint_path(out, options, Open, &path.0, color, width);
}
PaintCmd::LinePath {
points,
@ -532,7 +551,7 @@ pub fn mesh_command(
let n = points.len();
if n >= 2 {
path.add_line(&points);
paint_path(out_mesh, options, Open, &path.0, color, width);
paint_path(out, options, Open, &path.0, color, width);
}
}
PaintCmd::Path {
@ -546,18 +565,11 @@ pub fn mesh_command(
closed,
"You asked to fill a path that is not closed. That makes no sense."
);
fill_closed_path(out_mesh, options, &path.0, fill_color);
fill_closed_path(out, options, &path.0, fill_color);
}
if let Some(outline) = outline {
let typ = if closed { Closed } else { Open };
paint_path(
out_mesh,
options,
typ,
&path.0,
outline.color,
outline.width,
);
paint_path(out, options, typ, &path.0, outline.color, outline.width);
}
}
PaintCmd::Rect {
@ -573,17 +585,10 @@ pub fn mesh_command(
path.add_rounded_rectangle(rect, corner_radius);
if let Some(fill_color) = fill_color {
fill_closed_path(out_mesh, options, &path.0, fill_color);
fill_closed_path(out, options, &path.0, fill_color);
}
if let Some(outline) = outline {
paint_path(
out_mesh,
options,
Closed,
&path.0,
outline.color,
outline.width,
);
paint_path(out, options, Closed, &path.0, outline.color, outline.width);
}
}
PaintCmd::Text {
@ -614,7 +619,7 @@ pub fn mesh_command(
uv: glyph.max,
color,
};
out_mesh.add_rect(top_left, bottom_right);
out.add_rect(top_left, bottom_right);
}
}
}
@ -623,11 +628,12 @@ pub fn mesh_command(
}
}
pub fn mesh_paint_commands(
options: MesherOptions,
/// Turns `PaintCmd`:s into sets of triangles
pub fn paint_commands_into_triangles(
options: PaintOptions,
fonts: &Fonts,
commands: Vec<(Rect, PaintCmd)>,
) -> Vec<(Rect, Mesh)> {
) -> Vec<(Rect, Triangles)> {
let mut reused_path = Path::default();
let mut batches = PaintBatches::default();
@ -635,16 +641,16 @@ pub fn mesh_paint_commands(
// TODO: cull(clip_rect, cmd)
if batches.is_empty() || batches.last().unwrap().0 != clip_rect {
batches.push((clip_rect, Mesh::default()));
batches.push((clip_rect, Triangles::default()));
}
let out_mesh = &mut batches.last_mut().unwrap().1;
mesh_command(&mut reused_path, options, fonts, cmd, out_mesh);
let out = &mut batches.last_mut().unwrap().1;
paint_command_into_triangles(&mut reused_path, options, fonts, cmd, out);
}
if options.debug_paint_clip_rects {
for (clip_rect, mesh) in &mut batches {
mesh_command(
for (clip_rect, triangles) in &mut batches {
paint_command_into_triangles(
&mut reused_path,
options,
fonts,
@ -654,7 +660,7 @@ pub fn mesh_paint_commands(
fill_color: None,
outline: Some(Outline::new(2.0, srgba(150, 255, 150, 255))),
},
mesh,
triangles,
)
}
}

View file

@ -93,7 +93,7 @@ impl TextureAtlas {
impl Texture {
pub fn ui(&self, ui: &mut crate::Ui) {
use crate::{
color::WHITE, containers::show_tooltip, label, math::*, Mesh, PaintCmd, Vertex,
color::WHITE, containers::show_tooltip, label, math::*, PaintCmd, Triangles, Vertex,
};
ui.add(label!(
@ -117,9 +117,9 @@ impl Texture {
uv: (self.width as u16 - 1, self.height as u16 - 1),
color: WHITE,
};
let mut mesh = Mesh::default();
mesh.add_rect(top_left, bottom_right);
ui.add_paint_cmd(PaintCmd::Mesh(mesh));
let mut triangles = Triangles::default();
triangles.add_rect(top_left, bottom_right);
ui.add_paint_cmd(PaintCmd::Triangles(triangles));
if interact.hovered {
show_tooltip(ui.ctx(), |ui| {
@ -142,9 +142,9 @@ impl Texture {
uv: ((u + texel_radius) as u16, (v + texel_radius) as u16),
color: WHITE,
};
let mut mesh = Mesh::default();
mesh.add_rect(top_left, bottom_right);
ui.add_paint_cmd(PaintCmd::Mesh(mesh));
let mut triangles = Triangles::default();
triangles.add_rect(top_left, bottom_right);
ui.add_paint_cmd(PaintCmd::Triangles(triangles));
});
}
}

View file

@ -7,7 +7,7 @@ use crate::{
font::Galley,
fonts::TextStyle,
math::{Pos2, Rect},
mesher::{Mesh, Path},
mesher::{Path, Triangles},
Context, Ui,
};
@ -174,8 +174,7 @@ pub enum PaintCmd {
text_style: TextStyle, // TODO: Font?
color: Color,
},
/// Low-level triangle mesh
Mesh(Mesh),
Triangles(Triangles),
}
impl PaintCmd {

View file

@ -1,7 +1,7 @@
#![allow(deprecated)] // legacy implement_vertex macro
use {
emigui::{Mesh, PaintBatches, Rect},
emigui::{PaintBatches, Rect, Triangles},
glium::{implement_vertex, index::PrimitiveType, program, texture, uniform, Frame, Surface},
};
@ -220,8 +220,8 @@ impl Painter {
let mut target = display.draw();
target.clear_color(0.0, 0.0, 0.0, 0.0);
for (clip_rect, mesh) in batches {
self.paint_batch(&mut target, display, clip_rect, &mesh, texture)
for (clip_rect, triangles) in batches {
self.paint_batch(&mut target, display, clip_rect, &triangles, texture)
}
target.finish().unwrap();
}
@ -232,7 +232,7 @@ impl Painter {
target: &mut Frame,
display: &glium::Display,
clip_rect: Rect,
mesh: &Mesh,
triangles: &Triangles,
texture: &emigui::Texture,
) {
let vertex_buffer = {
@ -244,7 +244,7 @@ impl Painter {
}
implement_vertex!(Vertex, a_pos, a_color, a_tc);
let vertices: Vec<Vertex> = mesh
let vertices: Vec<Vertex> = triangles
.vertices
.iter()
.map(|v| Vertex {
@ -257,7 +257,7 @@ impl Painter {
glium::VertexBuffer::new(display, &vertices).unwrap()
};
let indices: Vec<u32> = mesh.indices.iter().map(|idx| *idx as u32).collect();
let indices: Vec<u32> = triangles.indices.iter().map(|idx| *idx as u32).collect();
let index_buffer =
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &indices).unwrap();

View file

@ -4,7 +4,7 @@ use {
web_sys::{WebGlBuffer, WebGlProgram, WebGlRenderingContext, WebGlShader, WebGlTexture},
};
use emigui::{vec2, Color, Mesh, PaintBatches, Pos2, Texture};
use emigui::{vec2, Color, PaintBatches, Pos2, Texture, Triangles};
type Gl = WebGlRenderingContext;
@ -209,7 +209,7 @@ impl Painter {
);
gl.clear(Gl::COLOR_BUFFER_BIT);
for (clip_rect, mesh) in batches {
for (clip_rect, triangles) in batches {
// Avoid infinities in shader:
let clip_min = clip_rect.min.max(Pos2::default());
let clip_max = clip_rect.max.min(Pos2::default() + screen_size_points);
@ -222,27 +222,27 @@ impl Painter {
clip_max.y,
);
for mesh in mesh.split_to_u16() {
self.paint_mesh(&mesh)?;
for triangles in triangles.split_to_u16() {
self.paint_triangles(&triangles)?;
}
}
Ok(())
}
fn paint_mesh(&self, mesh: &Mesh) -> Result<(), JsValue> {
let indices: Vec<u16> = mesh.indices.iter().map(|idx| *idx as u16).collect();
fn paint_triangles(&self, triangles: &Triangles) -> Result<(), JsValue> {
let indices: Vec<u16> = triangles.indices.iter().map(|idx| *idx as u16).collect();
let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
let mut tex_coords: Vec<u16> = Vec::with_capacity(2 * mesh.vertices.len());
for v in &mesh.vertices {
let mut positions: Vec<f32> = Vec::with_capacity(2 * triangles.vertices.len());
let mut tex_coords: Vec<u16> = Vec::with_capacity(2 * triangles.vertices.len());
for v in &triangles.vertices {
positions.push(v.pos.x);
positions.push(v.pos.y);
tex_coords.push(v.uv.0);
tex_coords.push(v.uv.1);
}
let mut colors: Vec<u8> = Vec::with_capacity(4 * mesh.vertices.len());
for v in &mesh.vertices {
let mut colors: Vec<u8> = Vec::with_capacity(4 * triangles.vertices.len());
for v in &triangles.vertices {
colors.push(v.color.r);
colors.push(v.color.g);
colors.push(v.color.b);