diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 8ce04a7ba9a60a..0b2bea277f210e 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,3 +1,5 @@ +mod conversions; + use crate::{ pipeline::{IndexFormat, PrimitiveTopology, RenderPipelines, VertexFormat}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, @@ -174,84 +176,6 @@ impl From<&VertexAttributeValues> for VertexFormat { } } -impl From> for VertexAttributeValues { - fn from(vec: Vec) -> Self { - VertexAttributeValues::Float(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec) -> Self { - VertexAttributeValues::Int(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec) -> Self { - VertexAttributeValues::Uint(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[f32; 2]>) -> Self { - VertexAttributeValues::Float2(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[i32; 2]>) -> Self { - VertexAttributeValues::Int2(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[u32; 2]>) -> Self { - VertexAttributeValues::Uint2(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[f32; 3]>) -> Self { - VertexAttributeValues::Float3(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[i32; 3]>) -> Self { - VertexAttributeValues::Int3(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[u32; 3]>) -> Self { - VertexAttributeValues::Uint3(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[f32; 4]>) -> Self { - VertexAttributeValues::Float4(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[i32; 4]>) -> Self { - VertexAttributeValues::Int4(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[u32; 4]>) -> Self { - VertexAttributeValues::Uint4(vec) - } -} - -impl From> for VertexAttributeValues { - fn from(vec: Vec<[u8; 4]>) -> Self { - VertexAttributeValues::Uchar4Norm(vec) - } -} - /// An array of indices into the VertexAttributeValues for a mesh. /// /// It describes the order in which the vertex attributes should be joined into faces. diff --git a/crates/bevy_render/src/mesh/mesh/conversions.rs b/crates/bevy_render/src/mesh/mesh/conversions.rs new file mode 100644 index 00000000000000..6eb1e3c1bc59eb --- /dev/null +++ b/crates/bevy_render/src/mesh/mesh/conversions.rs @@ -0,0 +1,606 @@ +//! These implementations allow you to +//! convert std::vec::Vec to VertexAttributeValues::T and back. +//! +//! # Examples +//! +//! ```rust +//! use bevy_render::mesh::VertexAttributeValues; +//! use std::convert::{ TryInto, TryFrom }; +//! +//! // creating std::vec::Vec +//! let buffer = vec![[0_u32; 4]; 10]; +//! +//! // converting std::vec::Vec to bevy_render::mesh::VertexAttributeValues +//! let values = VertexAttributeValues::from(buffer.clone()).clone(); +//! +//! // converting bevy_render::mesh::VertexAttributeValues to std::vec::Vec with two ways +//! let result_into: Vec<[u32; 4]> = values.clone().try_into().unwrap(); +//! let result_from: Vec<[u32; 4]> = Vec::try_from(values.clone()).unwrap(); +//! +//! // getting an error when trying to convert incorrectly +//! let error: Result, _> = values.try_into(); +//! +//! assert_eq!(buffer, result_into); +//! assert_eq!(buffer, result_from); +//! assert!(error.is_err()); +//! ``` + +use crate::mesh::VertexAttributeValues; +use std::{convert::TryFrom, error::Error, fmt}; + +#[derive(Debug, Clone)] +pub struct FromVertexAttributeError { + from: VertexAttributeValues, + into: &'static str, +} + +impl Error for FromVertexAttributeError {} + +impl fmt::Display for FromVertexAttributeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let value_name = match self.from { + VertexAttributeValues::Float(..) => "VertexAttributeValues::Float", + VertexAttributeValues::Int(..) => "VertexAttributeValues::Int", + VertexAttributeValues::Uint(..) => "VertexAttributeValues::Uint", + VertexAttributeValues::Float2(..) => "VertexAttributeValues::Float2", + VertexAttributeValues::Int2(..) => "VertexAttributeValues::Int2", + VertexAttributeValues::Uint2(..) => "VertexAttributeValues::Uint2", + VertexAttributeValues::Float3(..) => "VertexAttributeValues::Float3", + VertexAttributeValues::Int3(..) => "VertexAttributeValues::Int3", + VertexAttributeValues::Uint3(..) => "VertexAttributeValues::Uint3", + VertexAttributeValues::Float4(..) => "VertexAttributeValues::Float4", + VertexAttributeValues::Int4(..) => "VertexAttributeValues::Int4", + VertexAttributeValues::Uint4(..) => "VertexAttributeValues::Uint4", + VertexAttributeValues::Short2(..) => "VertexAttributeValues::Short2", + VertexAttributeValues::Short2Norm(..) => "VertexAttributeValues::Short2Norm", + VertexAttributeValues::Ushort2(..) => "VertexAttributeValues::Ushort2", + VertexAttributeValues::Ushort2Norm(..) => "VertexAttributeValues::Ushort2Norm", + VertexAttributeValues::Short4(..) => "VertexAttributeValues::Short4", + VertexAttributeValues::Short4Norm(..) => "VertexAttributeValues::Short4Norm", + VertexAttributeValues::Ushort4(..) => "VertexAttributeValues::Ushort4", + VertexAttributeValues::Ushort4Norm(..) => "VertexAttributeValues::Ushort4Norm", + VertexAttributeValues::Char2(..) => "VertexAttributeValues::Char2", + VertexAttributeValues::Char2Norm(..) => "VertexAttributeValues::Char2Norm", + VertexAttributeValues::Uchar2(..) => "VertexAttributeValues::Uchar2", + VertexAttributeValues::Uchar2Norm(..) => "VertexAttributeValues::Uchar2Norm", + VertexAttributeValues::Char4(..) => "VertexAttributeValues::Char4", + VertexAttributeValues::Char4Norm(..) => "VertexAttributeValues::Char4Norm", + VertexAttributeValues::Uchar4(..) => "VertexAttributeValues::Uchar4", + VertexAttributeValues::Uchar4Norm(..) => "VertexAttributeValues::Uchar4Norm", + }; + write!(f, "can't convert `{}` to `{}`", value_name, self.into) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec) -> Self { + VertexAttributeValues::Float(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec) -> Self { + VertexAttributeValues::Int(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec) -> Self { + VertexAttributeValues::Uint(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 2]>) -> Self { + VertexAttributeValues::Float2(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[i32; 2]>) -> Self { + VertexAttributeValues::Int2(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[u32; 2]>) -> Self { + VertexAttributeValues::Uint2(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 3]>) -> Self { + VertexAttributeValues::Float3(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[i32; 3]>) -> Self { + VertexAttributeValues::Int3(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[u32; 3]>) -> Self { + VertexAttributeValues::Uint3(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 4]>) -> Self { + VertexAttributeValues::Float4(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[i32; 4]>) -> Self { + VertexAttributeValues::Int4(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[u32; 4]>) -> Self { + VertexAttributeValues::Uint4(vec) + } +} + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[u8; 4]>) -> Self { + VertexAttributeValues::Uchar4Norm(vec) + } +} + +impl TryFrom for Vec<[u8; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uchar4(value) => Ok(value), + VertexAttributeValues::Uchar4Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u8; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[i8; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Char4(value) => Ok(value), + VertexAttributeValues::Char4Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i8; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[u8; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uchar2(value) => Ok(value), + VertexAttributeValues::Uchar2Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u8; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[i8; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Char2(value) => Ok(value), + VertexAttributeValues::Char2Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i8; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[i16; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Short4(value) => Ok(value), + VertexAttributeValues::Short4Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i16; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[u16; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Ushort4(value) => Ok(value), + VertexAttributeValues::Ushort4Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u16; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[u16; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Ushort2(value) => Ok(value), + VertexAttributeValues::Ushort2Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i16; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[i16; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Short2(value) => Ok(value), + VertexAttributeValues::Short2Norm(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i16; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[u32; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uint4(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u32; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[i32; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Int4(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i32; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[f32; 4]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Float4(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[f32; 4]>", + }), + } + } +} + +impl TryFrom for Vec<[u32; 3]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uint3(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u32; 3]>", + }), + } + } +} + +impl TryFrom for Vec<[i32; 3]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Int3(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i32; 3]>", + }), + } + } +} + +impl TryFrom for Vec<[f32; 3]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Float3(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[f32; 3]>", + }), + } + } +} + +impl TryFrom for Vec<[u32; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uint2(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[u32; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[i32; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Int2(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[i32; 2]>", + }), + } + } +} + +impl TryFrom for Vec<[f32; 2]> { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Float2(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec<[f32; 2]>", + }), + } + } +} + +impl TryFrom for Vec { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Uint(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec", + }), + } + } +} + +impl TryFrom for Vec { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Int(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec", + }), + } + } +} + +impl TryFrom for Vec { + type Error = FromVertexAttributeError; + + fn try_from(value: VertexAttributeValues) -> Result { + match value { + VertexAttributeValues::Float(value) => Ok(value), + _ => Err(FromVertexAttributeError { + from: value, + into: "Vec", + }), + } + } +} + +#[cfg(test)] +mod tests { + use super::VertexAttributeValues; + use std::convert::{TryFrom, TryInto}; + + #[test] + fn f32() { + let buffer = vec![0.0; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec = values.clone().try_into().unwrap(); + let result_from: Vec = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn i32() { + let buffer = vec![0; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec = values.clone().try_into().unwrap(); + let result_from: Vec = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn u32() { + let buffer = vec![0_u32; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec = values.clone().try_into().unwrap(); + let result_from: Vec = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn f32_2() { + let buffer = vec![[0.0; 2]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[f32; 2]> = values.clone().try_into().unwrap(); + let result_from: Vec<[f32; 2]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn i32_2() { + let buffer = vec![[0; 2]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[i32; 2]> = values.clone().try_into().unwrap(); + let result_from: Vec<[i32; 2]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn u32_2() { + let buffer = vec![[0_u32; 2]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[u32; 2]> = values.clone().try_into().unwrap(); + let result_from: Vec<[u32; 2]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn f32_3() { + let buffer = vec![[0.0; 3]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[f32; 3]> = values.clone().try_into().unwrap(); + let result_from: Vec<[f32; 3]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn i32_3() { + let buffer = vec![[0; 3]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[i32; 3]> = values.clone().try_into().unwrap(); + let result_from: Vec<[i32; 3]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn u32_3() { + let buffer = vec![[0_u32; 3]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[u32; 3]> = values.clone().try_into().unwrap(); + let result_from: Vec<[u32; 3]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn f32_4() { + let buffer = vec![[0.0; 4]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[f32; 4]> = values.clone().try_into().unwrap(); + let result_from: Vec<[f32; 4]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn i32_4() { + let buffer = vec![[0; 4]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[i32; 4]> = values.clone().try_into().unwrap(); + let result_from: Vec<[i32; 4]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn u32_4() { + let buffer = vec![[0_u32; 4]; 10]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let result_into: Vec<[u32; 4]> = values.clone().try_into().unwrap(); + let result_from: Vec<[u32; 4]> = Vec::try_from(values.clone()).unwrap(); + let error: Result, _> = values.try_into(); + assert_eq!(buffer, result_into); + assert_eq!(buffer, result_from); + assert!(error.is_err()); + } + + #[test] + fn correct_message() { + let buffer = vec![[0_u32; 4]; 3]; + let values = VertexAttributeValues::from(buffer.clone()).clone(); + let error_result: Result, _> = values.try_into(); + let error = match error_result { + Ok(..) => unreachable!(), + Err(error) => error, + }; + assert_eq!( + format!("{}", error), + "can't convert `VertexAttributeValues::Uint4` to `Vec`" + ); + assert_eq!(format!("{:?}", error), + "FromVertexAttributeError { from: Uint4([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), into: \"Vec\" }"); + } +}