Mesh::split_to_u16 now returns a 16-bit indexed Mesh16
This commit is contained in:
parent
b493bc6efc
commit
2a10747843
5 changed files with 77 additions and 22 deletions
|
@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
* `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`.
|
* Renamed `Triangles` to `Mesh`.
|
||||||
* The tesselator now wraps the clip rectangle and mesh in `struct ClippedMesh(Rect, Mesh)`.
|
* The tesselator now wraps the clip rectangle and mesh in `struct ClippedMesh(Rect, Mesh)`.
|
||||||
|
* `Mesh::split_to_u16` now returns a 16-bit indexed `Mesh16`.
|
||||||
|
|
||||||
### Fixed 🐛
|
### Fixed 🐛
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use {
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
math::clamp,
|
math::clamp,
|
||||||
paint::{Color32, Mesh, Texture},
|
paint::{Color32, Texture},
|
||||||
vec2,
|
vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -265,9 +265,8 @@ impl WebGlPainter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_mesh(&self, mesh: &Mesh) -> Result<(), JsValue> {
|
fn paint_mesh(&self, mesh: &egui::paint::Mesh16) -> Result<(), JsValue> {
|
||||||
debug_assert!(mesh.is_valid());
|
debug_assert!(mesh.is_valid());
|
||||||
let indices: Vec<u16> = mesh.indices.iter().map(|idx| *idx as u16).collect();
|
|
||||||
|
|
||||||
let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
||||||
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
||||||
|
@ -293,9 +292,9 @@ impl WebGlPainter {
|
||||||
let indices_memory_buffer = wasm_bindgen::memory()
|
let indices_memory_buffer = wasm_bindgen::memory()
|
||||||
.dyn_into::<WebAssembly::Memory>()?
|
.dyn_into::<WebAssembly::Memory>()?
|
||||||
.buffer();
|
.buffer();
|
||||||
let indices_ptr = indices.as_ptr() as u32 / 2;
|
let indices_ptr = mesh.indices.as_ptr() as u32 / 2;
|
||||||
let indices_array = js_sys::Int16Array::new(&indices_memory_buffer)
|
let indices_array = js_sys::Int16Array::new(&indices_memory_buffer)
|
||||||
.subarray(indices_ptr, indices_ptr + indices.len() as u32);
|
.subarray(indices_ptr, indices_ptr + mesh.indices.len() as u32);
|
||||||
|
|
||||||
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, Some(&self.index_buffer));
|
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, Some(&self.index_buffer));
|
||||||
gl.buffer_data_with_array_buffer_view(
|
gl.buffer_data_with_array_buffer_view(
|
||||||
|
@ -379,7 +378,12 @@ impl WebGlPainter {
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
gl.draw_elements_with_i32(Gl::TRIANGLES, indices.len() as i32, Gl::UNSIGNED_SHORT, 0);
|
gl.draw_elements_with_i32(
|
||||||
|
Gl::TRIANGLES,
|
||||||
|
mesh.indices.len() as i32,
|
||||||
|
Gl::UNSIGNED_SHORT,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use {
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
math::clamp,
|
math::clamp,
|
||||||
paint::{Color32, Mesh, Texture},
|
paint::{Color32, Texture},
|
||||||
vec2,
|
vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,9 +255,8 @@ impl WebGl2Painter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_mesh(&self, mesh: &Mesh) -> Result<(), JsValue> {
|
fn paint_mesh(&self, mesh: &egui::paint::Mesh16) -> Result<(), JsValue> {
|
||||||
debug_assert!(mesh.is_valid());
|
debug_assert!(mesh.is_valid());
|
||||||
let indices: Vec<u16> = mesh.indices.iter().map(|idx| *idx as u16).collect();
|
|
||||||
|
|
||||||
let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
let mut positions: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
||||||
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
let mut tex_coords: Vec<f32> = Vec::with_capacity(2 * mesh.vertices.len());
|
||||||
|
@ -283,9 +282,9 @@ impl WebGl2Painter {
|
||||||
let indices_memory_buffer = wasm_bindgen::memory()
|
let indices_memory_buffer = wasm_bindgen::memory()
|
||||||
.dyn_into::<WebAssembly::Memory>()?
|
.dyn_into::<WebAssembly::Memory>()?
|
||||||
.buffer();
|
.buffer();
|
||||||
let indices_ptr = indices.as_ptr() as u32 / 2;
|
let indices_ptr = mesh.indices.as_ptr() as u32 / 2;
|
||||||
let indices_array = js_sys::Int16Array::new(&indices_memory_buffer)
|
let indices_array = js_sys::Int16Array::new(&indices_memory_buffer)
|
||||||
.subarray(indices_ptr, indices_ptr + indices.len() as u32);
|
.subarray(indices_ptr, indices_ptr + mesh.indices.len() as u32);
|
||||||
|
|
||||||
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, Some(&self.index_buffer));
|
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, Some(&self.index_buffer));
|
||||||
gl.buffer_data_with_array_buffer_view(
|
gl.buffer_data_with_array_buffer_view(
|
||||||
|
@ -369,7 +368,12 @@ impl WebGl2Painter {
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
gl.draw_elements_with_i32(Gl::TRIANGLES, indices.len() as i32, Gl::UNSIGNED_SHORT, 0);
|
gl.draw_elements_with_i32(
|
||||||
|
Gl::TRIANGLES,
|
||||||
|
mesh.indices.len() as i32,
|
||||||
|
Gl::UNSIGNED_SHORT,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ mod texture_atlas;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
color::{Color32, Rgba},
|
color::{Color32, Rgba},
|
||||||
mesh::{Mesh, Vertex},
|
mesh::{Mesh, Mesh16, Vertex},
|
||||||
shadow::Shadow,
|
shadow::Shadow,
|
||||||
shape::Shape,
|
shape::Shape,
|
||||||
stats::PaintStats,
|
stats::PaintStats,
|
||||||
|
|
|
@ -25,6 +25,8 @@ pub struct Vertex {
|
||||||
pub struct Mesh {
|
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).
|
||||||
///
|
///
|
||||||
|
/// If you only support 16-bit indices you can use [`Mesh::split_to_u16`].
|
||||||
|
///
|
||||||
/// 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.
|
||||||
pub indices: Vec<u32>,
|
pub indices: Vec<u32>,
|
||||||
|
|
||||||
|
@ -51,8 +53,12 @@ impl Mesh {
|
||||||
|
|
||||||
/// Are all indices within the bounds of the contained vertices?
|
/// Are all indices within the bounds of the contained vertices?
|
||||||
pub fn is_valid(&self) -> bool {
|
pub fn is_valid(&self) -> bool {
|
||||||
let n = self.vertices.len() as u32;
|
if self.vertices.len() <= u32::MAX as usize {
|
||||||
self.indices.iter().all(|&i| i < n)
|
let n = self.vertices.len() as u32;
|
||||||
|
self.indices.iter().all(|&i| i < n)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
|
@ -149,13 +155,20 @@ impl Mesh {
|
||||||
|
|
||||||
/// This is for platforms that only support 16-bit index buffers.
|
/// This is for platforms that only support 16-bit index buffers.
|
||||||
///
|
///
|
||||||
/// 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`.
|
/// where the smaller meshes have 16-bit indices.
|
||||||
pub fn split_to_u16(self) -> Vec<Mesh> {
|
pub fn split_to_u16(self) -> Vec<Mesh16> {
|
||||||
|
debug_assert!(self.is_valid());
|
||||||
|
|
||||||
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 {
|
||||||
return vec![self]; // Common-case optimization
|
// Common-case optimization:
|
||||||
|
return vec![Mesh16 {
|
||||||
|
indices: self.indices.iter().map(|&i| i as u16).collect(),
|
||||||
|
vertices: self.vertices,
|
||||||
|
texture_id: self.texture_id,
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
@ -190,14 +203,17 @@ impl Mesh {
|
||||||
MAX_SIZE
|
MAX_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
output.push(Mesh {
|
use std::convert::TryFrom;
|
||||||
|
let mesh = Mesh16 {
|
||||||
indices: self.indices[span_start..index_cursor]
|
indices: self.indices[span_start..index_cursor]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|vi| vi - min_vindex)
|
.map(|vi| u16::try_from(vi - min_vindex).unwrap())
|
||||||
.collect(),
|
.collect(),
|
||||||
vertices: self.vertices[(min_vindex as usize)..=(max_vindex as usize)].to_vec(),
|
vertices: self.vertices[(min_vindex as usize)..=(max_vindex as usize)].to_vec(),
|
||||||
texture_id: self.texture_id,
|
texture_id: self.texture_id,
|
||||||
});
|
};
|
||||||
|
debug_assert!(mesh.is_valid());
|
||||||
|
output.push(mesh);
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
@ -209,3 +225,33 @@ impl Mesh {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// A version of [`Mesh`] that uses 16-bit indices.
|
||||||
|
///
|
||||||
|
/// This is produced by [`Mesh::split_to_u16`] and is meant to be used for legacy render backends.
|
||||||
|
pub struct Mesh16 {
|
||||||
|
/// 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.
|
||||||
|
pub indices: Vec<u16>,
|
||||||
|
|
||||||
|
/// The vertex data indexed by `indices`.
|
||||||
|
pub vertices: Vec<Vertex>,
|
||||||
|
|
||||||
|
/// The texture to use when drawing these triangles.
|
||||||
|
pub texture_id: TextureId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mesh16 {
|
||||||
|
/// Are all indices within the bounds of the contained vertices?
|
||||||
|
pub fn is_valid(&self) -> bool {
|
||||||
|
if self.vertices.len() <= u16::MAX as usize {
|
||||||
|
let n = self.vertices.len() as u16;
|
||||||
|
self.indices.iter().all(|&i| i < n)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue