Rename Triangles to Mesh

This commit is contained in:
Emil Ernerfeldt 2021-01-25 21:23:24 +01:00
parent 38ca36724a
commit 75fa77e040
18 changed files with 139 additions and 141 deletions

View file

@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* `Response::active` is now gone. You can use `response.dragged()` or `response.clicked()` instead. * `Response::active` is now gone. You can use `response.dragged()` or `response.clicked()` instead.
* Backend: pointer (mouse/touch) position and buttons are now passed to egui in the event stream. * Backend: pointer (mouse/touch) position and buttons are now passed to egui in the event stream.
* `DragValue::range` is now called `clamp_range` and also clamps incoming values. * `DragValue::range` is now called `clamp_range` and also clamps incoming values.
* Renamed `Triangles` to `Mesh`.
### Fixed 🐛 ### Fixed 🐛

View file

@ -160,7 +160,7 @@ impl Frame {
frame_shape frame_shape
} else { } else {
let shadow = shadow.tessellate(outer_rect, corner_radius); let shadow = shadow.tessellate(outer_rect, corner_radius);
let shadow = Shape::Triangles(shadow); let shadow = Shape::Mesh(shadow);
Shape::Vec(vec![shadow, frame_shape]) Shape::Vec(vec![shadow, frame_shape])
} }
} }

View file

@ -3,7 +3,7 @@ use crate::*;
impl Widget for &epaint::Texture { impl Widget for &epaint::Texture {
fn ui(self, ui: &mut Ui) -> Response { fn ui(self, ui: &mut Ui) -> Response {
use epaint::Triangles; use epaint::Mesh;
ui.vertical(|ui| { ui.vertical(|ui| {
// Show font texture in demo Ui // Show font texture in demo Ui
@ -19,13 +19,13 @@ impl Widget for &epaint::Texture {
size *= ui.available_width() / size.x; size *= ui.available_width() / size.x;
} }
let (rect, response) = ui.allocate_at_least(size, Sense::hover()); let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
triangles.add_rect_with_uv( mesh.add_rect_with_uv(
rect, rect,
[pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(),
Color32::WHITE, Color32::WHITE,
); );
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
let (tex_w, tex_h) = (self.width as f32, self.height as f32); let (tex_w, tex_h) = (self.width as f32, self.height as f32);
@ -45,9 +45,9 @@ impl Widget for &epaint::Texture {
pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h), pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h),
pos2((u + texel_radius) / tex_w, (v + texel_radius) / tex_h), pos2((u + texel_radius) / tex_w, (v + texel_radius) / tex_h),
); );
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
triangles.add_rect_with_uv(zoom_rect, uv_rect, Color32::WHITE); mesh.add_rect_with_uv(zoom_rect, uv_rect, Color32::WHITE);
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
}); });
}) })
.1 .1

View file

@ -26,20 +26,20 @@ fn background_checkers(painter: &Painter, rect: Rect) {
let checker_size = Vec2::splat(rect.height() / 2.0); let checker_size = Vec2::splat(rect.height() / 2.0);
let n = (rect.width() / checker_size.x).round() as u32; let n = (rect.width() / checker_size.x).round() as u32;
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
for i in 0..n { for i in 0..n {
let x = lerp(rect.left()..=rect.right(), i as f32 / (n as f32)); let x = lerp(rect.left()..=rect.right(), i as f32 / (n as f32));
triangles.add_colored_rect( mesh.add_colored_rect(
Rect::from_min_size(pos2(x, rect.top()), checker_size), Rect::from_min_size(pos2(x, rect.top()), checker_size),
top_color, top_color,
); );
triangles.add_colored_rect( mesh.add_colored_rect(
Rect::from_min_size(pos2(x, rect.center().y), checker_size), Rect::from_min_size(pos2(x, rect.center().y), checker_size),
bottom_color, bottom_color,
); );
std::mem::swap(&mut top_color, &mut bottom_color); std::mem::swap(&mut top_color, &mut bottom_color);
} }
painter.add(Shape::triangles(triangles)); painter.add(Shape::mesh(mesh));
} }
pub fn show_color(ui: &mut Ui, color: impl Into<Hsva>, desired_size: Vec2) -> Response { pub fn show_color(ui: &mut Ui, color: impl Into<Hsva>, desired_size: Vec2) -> Response {
@ -104,19 +104,19 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Color
{ {
// fill color: // fill color:
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
for i in 0..=N { for i in 0..=N {
let t = i as f32 / (N as f32); let t = i as f32 / (N as f32);
let color = color_at(t); let color = color_at(t);
let x = lerp(rect.left()..=rect.right(), t); let x = lerp(rect.left()..=rect.right(), t);
triangles.colored_vertex(pos2(x, rect.top()), color); mesh.colored_vertex(pos2(x, rect.top()), color);
triangles.colored_vertex(pos2(x, rect.bottom()), color); mesh.colored_vertex(pos2(x, rect.bottom()), color);
if i < N { if i < N {
triangles.add_triangle(2 * i + 0, 2 * i + 1, 2 * i + 2); mesh.add_triangle(2 * i + 0, 2 * i + 1, 2 * i + 2);
triangles.add_triangle(2 * i + 1, 2 * i + 2, 2 * i + 3); mesh.add_triangle(2 * i + 1, 2 * i + 2, 2 * i + 3);
} }
} }
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
} }
ui.painter().rect_stroke(rect, 0.0, visuals.bg_stroke); // outline ui.painter().rect_stroke(rect, 0.0, visuals.bg_stroke); // outline
@ -155,7 +155,7 @@ fn color_slider_2d(
} }
let visuals = ui.style().interact(&response); let visuals = ui.style().interact(&response);
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
for xi in 0..=N { for xi in 0..=N {
for yi in 0..=N { for yi in 0..=N {
@ -164,18 +164,18 @@ fn color_slider_2d(
let color = color_at(xt, yt); let color = color_at(xt, yt);
let x = lerp(rect.left()..=rect.right(), xt); let x = lerp(rect.left()..=rect.right(), xt);
let y = lerp(rect.bottom()..=rect.top(), yt); let y = lerp(rect.bottom()..=rect.top(), yt);
triangles.colored_vertex(pos2(x, y), color); mesh.colored_vertex(pos2(x, y), color);
if xi < N && yi < N { if xi < N && yi < N {
let x_offset = 1; let x_offset = 1;
let y_offset = N + 1; let y_offset = N + 1;
let tl = yi * y_offset + xi; let tl = yi * y_offset + xi;
triangles.add_triangle(tl, tl + x_offset, tl + y_offset); mesh.add_triangle(tl, tl + x_offset, tl + y_offset);
triangles.add_triangle(tl + x_offset, tl + y_offset, tl + y_offset + x_offset); mesh.add_triangle(tl + x_offset, tl + y_offset, tl + y_offset + x_offset);
} }
} }
} }
ui.painter().add(Shape::triangles(triangles)); // fill ui.painter().add(Shape::mesh(mesh)); // fill
ui.painter().rect_stroke(rect, 0.0, visuals.bg_stroke); // outline ui.painter().rect_stroke(rect, 0.0, visuals.bg_stroke); // outline

View file

@ -57,16 +57,16 @@ impl Image {
} = self; } = self;
if *bg_fill != Default::default() { if *bg_fill != Default::default() {
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
triangles.add_colored_rect(rect, *bg_fill); mesh.add_colored_rect(rect, *bg_fill);
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
} }
{ {
// TODO: builder pattern for Triangles // TODO: builder pattern for Mesh
let mut triangles = Triangles::with_texture(*texture_id); let mut mesh = Mesh::with_texture(*texture_id);
triangles.add_rect_with_uv(rect, *uv, *tint); mesh.add_rect_with_uv(rect, *uv, *tint);
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
} }
} }
} }

View file

@ -302,26 +302,26 @@ fn vertex_gradient(ui: &mut Ui, bg_fill: Color32, gradient: &Gradient) -> Respon
use egui::paint::*; use egui::paint::*;
let (rect, response) = ui.allocate_at_least(GRADIENT_SIZE, Sense::hover()); let (rect, response) = ui.allocate_at_least(GRADIENT_SIZE, Sense::hover());
if bg_fill != Default::default() { if bg_fill != Default::default() {
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
triangles.add_colored_rect(rect, bg_fill); mesh.add_colored_rect(rect, bg_fill);
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
} }
{ {
let n = gradient.0.len(); let n = gradient.0.len();
assert!(n >= 2); assert!(n >= 2);
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
for (i, &color) in gradient.0.iter().enumerate() { for (i, &color) in gradient.0.iter().enumerate() {
let t = i as f32 / (n as f32 - 1.0); let t = i as f32 / (n as f32 - 1.0);
let x = lerp(rect.x_range(), t); let x = lerp(rect.x_range(), t);
triangles.colored_vertex(pos2(x, rect.top()), color); mesh.colored_vertex(pos2(x, rect.top()), color);
triangles.colored_vertex(pos2(x, rect.bottom()), color); mesh.colored_vertex(pos2(x, rect.bottom()), color);
if i < n - 1 { if i < n - 1 {
let i = i as u32; let i = i as u32;
triangles.add_triangle(2 * i, 2 * i + 1, 2 * i + 2); mesh.add_triangle(2 * i, 2 * i + 1, 2 * i + 2);
triangles.add_triangle(2 * i + 1, 2 * i + 2, 2 * i + 3); mesh.add_triangle(2 * i + 1, 2 * i + 2, 2 * i + 3);
} }
} }
ui.painter().add(Shape::triangles(triangles)); ui.painter().add(Shape::mesh(mesh));
} }
response response
} }

View file

@ -216,7 +216,7 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
let frame_time = (Instant::now() - frame_start).as_secs_f64() as f32; let frame_time = (Instant::now() - frame_start).as_secs_f64() as f32;
previous_frame_time = Some(frame_time); previous_frame_time = Some(frame_time);
painter.paint_jobs( painter.paint_meshes(
&display, &display,
ctx.pixels_per_point(), ctx.pixels_per_point(),
app.clear_color(), app.clear_color(),

View file

@ -3,7 +3,7 @@
use { use {
egui::{ egui::{
math::clamp, math::clamp,
paint::{PaintJobs, Triangles}, paint::{Mesh, PaintJobs},
Color32, Rect, Color32, Rect,
}, },
glium::{ glium::{
@ -123,7 +123,7 @@ impl Painter {
} }
/// Main entry-point for painting a frame /// Main entry-point for painting a frame
pub fn paint_jobs( pub fn paint_meshes(
&mut self, &mut self,
display: &glium::Display, display: &glium::Display,
pixels_per_point: f32, pixels_per_point: f32,
@ -142,28 +142,22 @@ impl Painter {
clear_color[2], clear_color[2],
clear_color[3], clear_color[3],
); );
for (clip_rect, triangles) in jobs { for (clip_rect, mesh) in jobs {
self.paint_job( self.paint_mesh(&mut target, display, pixels_per_point, clip_rect, &mesh)
&mut target,
display,
pixels_per_point,
clip_rect,
&triangles,
)
} }
target.finish().unwrap(); target.finish().unwrap();
} }
#[inline(never)] // Easier profiling #[inline(never)] // Easier profiling
pub fn paint_job( pub fn paint_mesh(
&mut self, &mut self,
target: &mut Frame, target: &mut Frame,
display: &glium::Display, display: &glium::Display,
pixels_per_point: f32, pixels_per_point: f32,
clip_rect: Rect, clip_rect: Rect,
triangles: &Triangles, mesh: &Mesh,
) { ) {
debug_assert!(triangles.is_valid()); debug_assert!(mesh.is_valid());
let vertex_buffer = { let vertex_buffer = {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -174,7 +168,7 @@ impl Painter {
} }
implement_vertex!(Vertex, a_pos, a_tc, a_srgba); implement_vertex!(Vertex, a_pos, a_tc, a_srgba);
let vertices: Vec<Vertex> = triangles let vertices: Vec<Vertex> = mesh
.vertices .vertices
.iter() .iter()
.map(|v| Vertex { .map(|v| Vertex {
@ -188,7 +182,7 @@ impl Painter {
glium::VertexBuffer::new(display, &vertices).unwrap() glium::VertexBuffer::new(display, &vertices).unwrap()
}; };
let indices: Vec<u32> = triangles.indices.iter().map(|idx| *idx as u32).collect(); let indices: Vec<u32> = mesh.indices.iter().map(|idx| *idx as u32).collect();
// TODO: we should probably reuse the `IndexBuffer` instead of allocating a new one each frame. // TODO: we should probably reuse the `IndexBuffer` instead of allocating a new one each frame.
let index_buffer = let index_buffer =
@ -198,7 +192,7 @@ impl Painter {
let width_in_points = width_in_pixels as f32 / pixels_per_point; let width_in_points = width_in_pixels as f32 / pixels_per_point;
let height_in_points = height_in_pixels as f32 / pixels_per_point; let height_in_points = height_in_pixels as f32 / pixels_per_point;
if let Some(texture) = self.get_texture(triangles.texture_id) { if let Some(texture) = self.get_texture(mesh.texture_id) {
// The texture coordinates for text are so that both nearest and linear should work with the egui font texture. // The texture coordinates for text are so that both nearest and linear should work with the egui font texture.
// For user textures linear sampling is more likely to be the right choice. // For user textures linear sampling is more likely to be the right choice.
let filter = MagnifySamplerFilter::Linear; let filter = MagnifySamplerFilter::Linear;
@ -227,7 +221,7 @@ impl Painter {
..Default::default() ..Default::default()
}; };
// egui outputs triangles in both winding orders: // egui outputs mesh in both winding orders:
let backface_culling = glium::BackfaceCullingMode::CullingDisabled; let backface_culling = glium::BackfaceCullingMode::CullingDisabled;
// Transform clip rect to physical pixels: // Transform clip rect to physical pixels:

View file

@ -65,7 +65,7 @@ impl WebBackend {
self.painter.upload_egui_texture(&self.ctx.texture()); self.painter.upload_egui_texture(&self.ctx.texture());
self.painter.clear(clear_color); self.painter.clear(clear_color);
self.painter self.painter
.paint_jobs(paint_jobs, self.ctx.pixels_per_point()) .paint_meshes(paint_jobs, self.ctx.pixels_per_point())
} }
pub fn painter_debug_info(&self) -> String { pub fn painter_debug_info(&self) -> String {

View file

@ -12,5 +12,6 @@ pub trait Painter {
fn clear(&mut self, lear_color: egui::Rgba); fn clear(&mut self, lear_color: egui::Rgba);
fn paint_jobs(&mut self, jobs: egui::PaintJobs, pixels_per_point: f32) -> Result<(), JsValue>; fn paint_meshes(&mut self, jobs: egui::PaintJobs, pixels_per_point: f32)
-> Result<(), JsValue>;
} }

View file

@ -6,7 +6,7 @@ use {
use egui::{ use egui::{
math::clamp, math::clamp,
paint::{Color32, PaintJobs, Texture, Triangles}, paint::{Color32, Mesh, PaintJobs, Texture},
vec2, vec2,
}; };
@ -265,21 +265,21 @@ impl WebGlPainter {
} }
} }
fn paint_triangles(&self, triangles: &Triangles) -> Result<(), JsValue> { fn paint_mesh(&self, mesh: &Mesh) -> Result<(), JsValue> {
debug_assert!(triangles.is_valid()); debug_assert!(mesh.is_valid());
let indices: Vec<u16> = triangles.indices.iter().map(|idx| *idx as u16).collect(); let indices: Vec<u16> = mesh.indices.iter().map(|idx| *idx as u16).collect();
let mut positions: Vec<f32> = Vec::with_capacity(2 * triangles.vertices.len()); let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * triangles.vertices.len()); let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
for v in &triangles.vertices { for v in &mesh.vertices {
positions.push(v.pos.x); positions.push(v.pos.x);
positions.push(v.pos.y); positions.push(v.pos.y);
tex_coords.push(v.uv.x); tex_coords.push(v.uv.x);
tex_coords.push(v.uv.y); tex_coords.push(v.uv.y);
} }
let mut colors: Vec<u8> = Vec::with_capacity(4 * triangles.vertices.len()); let mut colors: Vec<u8> = Vec::with_capacity(4 * mesh.vertices.len());
for v in &triangles.vertices { for v in &mesh.vertices {
colors.push(v.color[0]); colors.push(v.color[0]);
colors.push(v.color[1]); colors.push(v.color[1]);
colors.push(v.color[2]); colors.push(v.color[2]);
@ -478,7 +478,7 @@ impl crate::Painter for WebGlPainter {
gl.clear(Gl::COLOR_BUFFER_BIT); gl.clear(Gl::COLOR_BUFFER_BIT);
} }
fn paint_jobs(&mut self, jobs: PaintJobs, pixels_per_point: f32) -> Result<(), JsValue> { fn paint_meshes(&mut self, jobs: PaintJobs, pixels_per_point: f32) -> Result<(), JsValue> {
self.upload_user_textures(); self.upload_user_textures();
let gl = &self.gl; let gl = &self.gl;
@ -504,8 +504,8 @@ impl crate::Painter for WebGlPainter {
let u_sampler_loc = gl.get_uniform_location(&self.program, "u_sampler").unwrap(); let u_sampler_loc = gl.get_uniform_location(&self.program, "u_sampler").unwrap();
gl.uniform1i(Some(&u_sampler_loc), 0); gl.uniform1i(Some(&u_sampler_loc), 0);
for (clip_rect, triangles) in jobs { for (clip_rect, mesh) in jobs {
if let Some(gl_texture) = self.get_texture(triangles.texture_id) { if let Some(gl_texture) = self.get_texture(mesh.texture_id) {
gl.bind_texture(Gl::TEXTURE_2D, Some(gl_texture)); gl.bind_texture(Gl::TEXTURE_2D, Some(gl_texture));
let clip_min_x = pixels_per_point * clip_rect.min.x; let clip_min_x = pixels_per_point * clip_rect.min.x;
@ -529,13 +529,13 @@ impl crate::Painter for WebGlPainter {
clip_max_y - clip_min_y, clip_max_y - clip_min_y,
); );
for triangles in triangles.split_to_u16() { for mesh in mesh.split_to_u16() {
self.paint_triangles(&triangles)?; self.paint_mesh(&mesh)?;
} }
} else { } else {
crate::console_warn(format!( crate::console_warn(format!(
"WebGL: Failed to find texture {:?}", "WebGL: Failed to find texture {:?}",
triangles.texture_id mesh.texture_id
)); ));
} }
} }

View file

@ -8,7 +8,7 @@ use {
use egui::{ use egui::{
math::clamp, math::clamp,
paint::{Color32, PaintJobs, Texture, Triangles}, paint::{Color32, Mesh, PaintJobs, Texture},
vec2, vec2,
}; };
@ -255,21 +255,21 @@ impl WebGl2Painter {
} }
} }
fn paint_triangles(&self, triangles: &Triangles) -> Result<(), JsValue> { fn paint_mesh(&self, mesh: &Mesh) -> Result<(), JsValue> {
debug_assert!(triangles.is_valid()); debug_assert!(mesh.is_valid());
let indices: Vec<u16> = triangles.indices.iter().map(|idx| *idx as u16).collect(); let indices: Vec<u16> = mesh.indices.iter().map(|idx| *idx as u16).collect();
let mut positions: Vec<f32> = Vec::with_capacity(2 * triangles.vertices.len()); let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * triangles.vertices.len()); let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
for v in &triangles.vertices { for v in &mesh.vertices {
positions.push(v.pos.x); positions.push(v.pos.x);
positions.push(v.pos.y); positions.push(v.pos.y);
tex_coords.push(v.uv.x); tex_coords.push(v.uv.x);
tex_coords.push(v.uv.y); tex_coords.push(v.uv.y);
} }
let mut colors: Vec<u8> = Vec::with_capacity(4 * triangles.vertices.len()); let mut colors: Vec<u8> = Vec::with_capacity(4 * mesh.vertices.len());
for v in &triangles.vertices { for v in &mesh.vertices {
colors.push(v.color[0]); colors.push(v.color[0]);
colors.push(v.color[1]); colors.push(v.color[1]);
colors.push(v.color[2]); colors.push(v.color[2]);
@ -467,7 +467,7 @@ impl crate::Painter for WebGl2Painter {
gl.clear(Gl::COLOR_BUFFER_BIT); gl.clear(Gl::COLOR_BUFFER_BIT);
} }
fn paint_jobs(&mut self, jobs: PaintJobs, pixels_per_point: f32) -> Result<(), JsValue> { fn paint_meshes(&mut self, jobs: PaintJobs, pixels_per_point: f32) -> Result<(), JsValue> {
self.upload_user_textures(); self.upload_user_textures();
let gl = &self.gl; let gl = &self.gl;
@ -493,8 +493,8 @@ impl crate::Painter for WebGl2Painter {
let u_sampler_loc = gl.get_uniform_location(&self.program, "u_sampler").unwrap(); let u_sampler_loc = gl.get_uniform_location(&self.program, "u_sampler").unwrap();
gl.uniform1i(Some(&u_sampler_loc), 0); gl.uniform1i(Some(&u_sampler_loc), 0);
for (clip_rect, triangles) in jobs { for (clip_rect, mesh) in jobs {
if let Some(gl_texture) = self.get_texture(triangles.texture_id) { if let Some(gl_texture) = self.get_texture(mesh.texture_id) {
gl.bind_texture(Gl::TEXTURE_2D, Some(gl_texture)); gl.bind_texture(Gl::TEXTURE_2D, Some(gl_texture));
let clip_min_x = pixels_per_point * clip_rect.min.x; let clip_min_x = pixels_per_point * clip_rect.min.x;
@ -518,13 +518,13 @@ impl crate::Painter for WebGl2Painter {
clip_max_y - clip_min_y, clip_max_y - clip_min_y,
); );
for triangles in triangles.split_to_u16() { for mesh in mesh.split_to_u16() {
self.paint_triangles(&triangles)?; self.paint_mesh(&mesh)?;
} }
} else { } else {
crate::console_warn(format!( crate::console_warn(format!(
"WebGL: Failed to find texture {:?}", "WebGL: Failed to find texture {:?}",
triangles.texture_id mesh.texture_id
)); ));
} }
} }

View file

@ -45,6 +45,7 @@
#![allow(clippy::manual_range_contains)] #![allow(clippy::manual_range_contains)]
pub mod color; pub mod color;
mod mesh;
pub mod mutex; pub mod mutex;
mod shadow; mod shadow;
mod shape; mod shape;
@ -53,10 +54,10 @@ mod stroke;
pub mod tessellator; pub mod tessellator;
pub mod text; pub mod text;
mod texture_atlas; mod texture_atlas;
mod triangles;
pub use { pub use {
color::{Color32, Rgba}, color::{Color32, Rgba},
mesh::{Mesh, Vertex},
shadow::Shadow, shadow::Shadow,
shape::Shape, shape::Shape,
stats::PaintStats, stats::PaintStats,
@ -64,7 +65,6 @@ pub use {
tessellator::TessellationOptions, tessellator::TessellationOptions,
text::{Galley, TextStyle}, text::{Galley, TextStyle},
texture_atlas::{Texture, TextureAtlas}, texture_atlas::{Texture, TextureAtlas},
triangles::{Triangles, Vertex},
}; };
pub use ahash; pub use ahash;
@ -76,7 +76,7 @@ pub use emath;
/// (so it doesn't do bilinear blending with bottom right corner). /// (so it doesn't do bilinear blending with bottom right corner).
pub const WHITE_UV: emath::Pos2 = emath::pos2(0.0, 0.0); pub const WHITE_UV: emath::Pos2 = emath::pos2(0.0, 0.0);
/// What texture to use in a [`Triangles`] mesh. /// What texture to use in a [`Mesh`] mesh.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TextureId { pub enum TextureId {
/// The egui font texture. /// The egui font texture.
@ -115,7 +115,7 @@ pub struct ClippedShape(
); );
/// A clip triangle and some textured triangles, all in points (logical pixels). /// A clip triangle and some textured triangles, all in points (logical pixels).
pub type PaintJob = (emath::Rect, Triangles); pub type PaintJob = (emath::Rect, Mesh);
/// Grouped by clip rectangles, in points (logical pixels). /// Grouped by clip rectangles, in points (logical pixels).
pub type PaintJobs = Vec<PaintJob>; pub type PaintJobs = Vec<PaintJob>;

View file

@ -1,7 +1,7 @@
use crate::*; use crate::*;
use emath::*; use emath::*;
/// The vertex type. /// The 2D vertex type.
/// ///
/// Should be friendly to send to GPU as is. /// Should be friendly to send to GPU as is.
#[repr(C)] #[repr(C)]
@ -20,9 +20,9 @@ pub struct Vertex {
pub color: Color32, // 32 bit pub color: Color32, // 32 bit
} }
/// Textured triangles. /// Textured triangles in two dimensions.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct Triangles { pub struct Mesh {
/// Draw as triangles (i.e. the length is always multiple of three). /// Draw as triangles (i.e. the length is always multiple of three).
/// ///
/// egui is NOT consistent with what winding order it uses, so turn off backface culling. /// egui is NOT consistent with what winding order it uses, so turn off backface culling.
@ -35,7 +35,7 @@ pub struct Triangles {
pub texture_id: TextureId, pub texture_id: TextureId,
} }
impl Triangles { impl Mesh {
pub fn with_texture(texture_id: TextureId) -> Self { pub fn with_texture(texture_id: TextureId) -> Self {
Self { Self {
texture_id, texture_id,
@ -60,7 +60,7 @@ impl Triangles {
} }
/// Append all the indices and vertices of `other` to `self`. /// Append all the indices and vertices of `other` to `self`.
pub fn append(&mut self, other: Triangles) { pub fn append(&mut self, other: Mesh) {
debug_assert!(other.is_valid()); debug_assert!(other.is_valid());
if self.is_empty() { if self.is_empty() {
@ -68,7 +68,7 @@ impl Triangles {
} else { } else {
assert_eq!( assert_eq!(
self.texture_id, other.texture_id, self.texture_id, other.texture_id,
"Can't merge Triangles using different textures" "Can't merge Mesh using different textures"
); );
let index_offset = self.vertices.len() as u32; let index_offset = self.vertices.len() as u32;
@ -151,7 +151,7 @@ impl Triangles {
/// ///
/// Splits this mesh into many smaller meshes (if needed). /// Splits this mesh into many smaller meshes (if needed).
/// All the returned meshes will have indices that fit into a `u16`. /// All the returned meshes will have indices that fit into a `u16`.
pub fn split_to_u16(self) -> Vec<Triangles> { pub fn split_to_u16(self) -> Vec<Mesh> {
const MAX_SIZE: u32 = 1 << 16; const MAX_SIZE: u32 = 1 << 16;
if self.vertices.len() < MAX_SIZE as usize { if self.vertices.len() < MAX_SIZE as usize {
@ -190,7 +190,7 @@ impl Triangles {
MAX_SIZE MAX_SIZE
); );
output.push(Triangles { output.push(Mesh {
indices: self.indices[span_start..index_cursor] indices: self.indices[span_start..index_cursor]
.iter() .iter()
.map(|vi| vi - min_vindex) .map(|vi| vi - min_vindex)

View file

@ -30,7 +30,7 @@ impl Shadow {
} }
} }
pub fn tessellate(&self, rect: emath::Rect, corner_radius: f32) -> Triangles { pub fn tessellate(&self, rect: emath::Rect, corner_radius: f32) -> Mesh {
// tessellator.clip_rect = clip_rect; // TODO: culling // tessellator.clip_rect = clip_rect; // TODO: culling
let Self { extrusion, color } = *self; let Self { extrusion, color } = *self;
@ -47,8 +47,8 @@ impl Shadow {
anti_alias: true, anti_alias: true,
..Default::default() ..Default::default()
}); });
let mut triangles = Triangles::default(); let mut mesh = Mesh::default();
tessellator.tessellate_rect(&rect, &mut triangles); tessellator.tessellate_rect(&rect, &mut mesh);
triangles mesh
} }
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
text::{Fonts, Galley, TextStyle}, text::{Fonts, Galley, TextStyle},
Color32, Stroke, Triangles, Color32, Mesh, Stroke,
}; };
use emath::*; use emath::*;
@ -47,7 +47,7 @@ pub enum Shape {
text_style: TextStyle, // TODO: Font? text_style: TextStyle, // TODO: Font?
color: Color32, color: Color32,
}, },
Triangles(Triangles), Mesh(Mesh),
} }
/// ## Constructors /// ## Constructors
@ -144,14 +144,19 @@ impl Shape {
/// ## Operations /// ## Operations
impl Shape { impl Shape {
pub fn triangles(triangles: Triangles) -> Self { pub fn mesh(mesh: Mesh) -> Self {
debug_assert!(triangles.is_valid()); debug_assert!(mesh.is_valid());
Self::Triangles(triangles) Self::Mesh(mesh)
}
#[deprecated = "Renamed `mesh`"]
pub fn triangles(mesh: Mesh) -> Self {
Self::mesh(mesh)
} }
pub fn texture_id(&self) -> super::TextureId { pub fn texture_id(&self) -> super::TextureId {
if let Shape::Triangles(triangles) = self { if let Shape::Mesh(mesh) = self {
triangles.texture_id mesh.texture_id
} else { } else {
super::TextureId::Egui super::TextureId::Egui
} }
@ -185,8 +190,8 @@ impl Shape {
Shape::Text { pos, .. } => { Shape::Text { pos, .. } => {
*pos += delta; *pos += delta;
} }
Shape::Triangles(triangles) => { Shape::Mesh(mesh) => {
triangles.translate(delta); mesh.translate(delta);
} }
} }
} }

View file

@ -67,7 +67,7 @@ impl AllocInfo {
// | Shape::Rect { .. } => Self::default(), // | Shape::Rect { .. } => Self::default(),
// Shape::Path { points, .. } => Self::from_slice(points), // Shape::Path { points, .. } => Self::from_slice(points),
// Shape::Text { galley, .. } => Self::from_galley(galley), // Shape::Text { galley, .. } => Self::from_galley(galley),
// Shape::Triangles(triangles) => Self::from_triangles(triangles), // Shape::Mesh(mesh) => Self::from_mesh(mesh),
// } // }
// } // }
@ -75,8 +75,8 @@ impl AllocInfo {
Self::from_slice(galley.text.as_bytes()) + Self::from_slice(&galley.rows) Self::from_slice(galley.text.as_bytes()) + Self::from_slice(&galley.rows)
} }
pub fn from_triangles(triangles: &Triangles) -> Self { pub fn from_mesh(mesh: &Mesh) -> Self {
Self::from_slice(&triangles.indices) + Self::from_slice(&triangles.vertices) Self::from_slice(&mesh.indices) + Self::from_slice(&mesh.vertices)
} }
pub fn from_slice<T>(slice: &[T]) -> Self { pub fn from_slice<T>(slice: &[T]) -> Self {
@ -182,8 +182,8 @@ impl PaintStats {
Shape::Text { galley, .. } => { Shape::Text { galley, .. } => {
self.shape_text += AllocInfo::from_galley(galley); self.shape_text += AllocInfo::from_galley(galley);
} }
Shape::Triangles(triangles) => { Shape::Mesh(mesh) => {
self.shape_mesh += AllocInfo::from_triangles(triangles); self.shape_mesh += AllocInfo::from_mesh(mesh);
} }
} }
} }

View file

@ -1,7 +1,7 @@
//! Converts graphics primitives into textured triangles. //! Converts graphics primitives into textured triangles.
//! //!
//! This module converts lines, circles, text and more represented by [`Shape`] //! This module converts lines, circles, text and more represented by [`Shape`]
//! into textured triangles represented by [`Triangles`]. //! into textured triangles represented by [`Mesh`].
#![allow(clippy::identity_op)] #![allow(clippy::identity_op)]
@ -239,7 +239,7 @@ fn fill_closed_path(
path: &[PathPoint], path: &[PathPoint],
color: Color32, color: Color32,
options: TessellationOptions, options: TessellationOptions,
out: &mut Triangles, out: &mut Mesh,
) { ) {
if color == Color32::TRANSPARENT { if color == Color32::TRANSPARENT {
return; return;
@ -285,7 +285,7 @@ fn stroke_path(
path_type: PathType, path_type: PathType,
stroke: Stroke, stroke: Stroke,
options: TessellationOptions, options: TessellationOptions,
out: &mut Triangles, out: &mut Mesh,
) { ) {
if stroke.width <= 0.0 || stroke.color == Color32::TRANSPARENT { if stroke.width <= 0.0 || stroke.color == Color32::TRANSPARENT {
return; return;
@ -427,7 +427,7 @@ fn mul_color(color: Color32, factor: f32) -> Color32 {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/// Converts [`Shape`]s into [`Triangles`]. /// Converts [`Shape`]s into [`Mesh`].
pub struct Tessellator { pub struct Tessellator {
options: TessellationOptions, options: TessellationOptions,
/// Only used for culling /// Only used for culling
@ -446,7 +446,7 @@ impl Tessellator {
} }
} }
/// Tessellate a single [`Shape`] into a [`Triangles`]. /// Tessellate a single [`Shape`] into a [`Mesh`].
/// ///
/// * `shape`: the shape to tessellate /// * `shape`: the shape to tessellate
/// * `options`: tessellation quality /// * `options`: tessellation quality
@ -454,7 +454,7 @@ impl Tessellator {
/// * `out`: where the triangles are put /// * `out`: where the triangles are put
/// * `scratchpad_path`: if you plan to run `tessellate_shape` /// * `scratchpad_path`: if you plan to run `tessellate_shape`
/// many times, pass it a reference to the same `Path` to avoid excessive allocations. /// many times, pass it a reference to the same `Path` to avoid excessive allocations.
pub fn tessellate_shape(&mut self, fonts: &Fonts, shape: Shape, out: &mut Triangles) { pub fn tessellate_shape(&mut self, fonts: &Fonts, shape: Shape, out: &mut Mesh) {
let clip_rect = self.clip_rect; let clip_rect = self.clip_rect;
let options = self.options; let options = self.options;
@ -487,11 +487,11 @@ impl Tessellator {
fill_closed_path(&path.0, fill, options, out); fill_closed_path(&path.0, fill, options, out);
stroke_path(&path.0, Closed, stroke, options, out); stroke_path(&path.0, Closed, stroke, options, out);
} }
Shape::Triangles(triangles) => { Shape::Mesh(mesh) => {
if triangles.is_valid() { if mesh.is_valid() {
out.append(triangles); out.append(mesh);
} else { } else {
debug_assert!(false, "Invalid Triangles in Shape::Triangles"); debug_assert!(false, "Invalid Mesh in Shape::Mesh");
} }
} }
Shape::LineSegment { points, stroke } => { Shape::LineSegment { points, stroke } => {
@ -562,7 +562,7 @@ impl Tessellator {
} }
} }
pub(crate) fn tessellate_rect(&mut self, rect: &PaintRect, out: &mut Triangles) { pub(crate) fn tessellate_rect(&mut self, rect: &PaintRect, out: &mut Mesh) {
let PaintRect { let PaintRect {
mut rect, mut rect,
corner_radius, corner_radius,
@ -599,7 +599,7 @@ impl Tessellator {
galley: &super::Galley, galley: &super::Galley,
text_style: super::TextStyle, text_style: super::TextStyle,
color: Color32, color: Color32,
out: &mut Triangles, out: &mut Mesh,
) { ) {
if color == Color32::TRANSPARENT { if color == Color32::TRANSPARENT {
return; return;
@ -663,12 +663,12 @@ impl Tessellator {
/// * `fonts`: font source when tessellating text /// * `fonts`: font source when tessellating text
/// ///
/// ## Returns /// ## Returns
/// A list of clip rectangles with matching [`Triangles`]. /// A list of clip rectangles with matching [`Mesh`].
pub fn tessellate_shapes( pub fn tessellate_shapes(
shapes: Vec<ClippedShape>, shapes: Vec<ClippedShape>,
options: TessellationOptions, options: TessellationOptions,
fonts: &Fonts, fonts: &Fonts,
) -> Vec<(Rect, Triangles)> { ) -> Vec<(Rect, Mesh)> {
let mut tessellator = Tessellator::from_options(options); let mut tessellator = Tessellator::from_options(options);
let mut jobs = PaintJobs::default(); let mut jobs = PaintJobs::default();
@ -679,7 +679,7 @@ pub fn tessellate_shapes(
}; };
if start_new_job { if start_new_job {
jobs.push((clip_rect, Triangles::default())); jobs.push((clip_rect, Mesh::default()));
} }
let out = &mut jobs.last_mut().unwrap().1; let out = &mut jobs.last_mut().unwrap().1;
@ -688,7 +688,7 @@ pub fn tessellate_shapes(
} }
if options.debug_paint_clip_rects { if options.debug_paint_clip_rects {
for (clip_rect, triangles) in &mut jobs { for (clip_rect, mesh) in &mut jobs {
tessellator.clip_rect = Rect::everything(); tessellator.clip_rect = Rect::everything();
tessellator.tessellate_shape( tessellator.tessellate_shape(
fonts, fonts,
@ -698,7 +698,7 @@ pub fn tessellate_shapes(
fill: Default::default(), fill: Default::default(),
stroke: Stroke::new(2.0, Color32::from_rgb(150, 255, 150)), stroke: Stroke::new(2.0, Color32::from_rgb(150, 255, 150)),
}, },
triangles, mesh,
) )
} }
} }
@ -709,11 +709,8 @@ pub fn tessellate_shapes(
} }
} }
for (_, triangles) in &jobs { for (_, mesh) in &jobs {
debug_assert!( debug_assert!(mesh.is_valid(), "Tessellator generated invalid Mesh");
triangles.is_valid(),
"Tessellator generated invalid Triangles"
);
} }
jobs jobs