use std::fmt;
use std::str::FromStr;
use super::error::{Error, Result};
#[derive(Debug, Clone)]
pub struct Displacement2D {
pub id: u32,
pub path: String,
pub channel: ChannelName,
pub tile_style_u: TileStyle,
pub tile_style_v: TileStyle,
pub filter: Filter,
}
impl Displacement2D {
pub fn new(id: u32, path: impl Into<String>) -> Self {
Self {
id,
path: path.into(),
channel: ChannelName::default(),
tile_style_u: TileStyle::default(),
tile_style_v: TileStyle::default(),
filter: Filter::default(),
}
}
pub fn set_channel(&mut self, channel: ChannelName) -> &mut Self {
self.channel = channel;
self
}
pub fn set_tile_style_u(&mut self, tile_style: TileStyle) -> &mut Self {
self.tile_style_u = tile_style;
self
}
pub fn set_tile_style_v(&mut self, tile_style: TileStyle) -> &mut Self {
self.tile_style_v = tile_style;
self
}
pub fn set_filter(&mut self, filter: Filter) -> &mut Self {
self.filter = filter;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChannelName {
R,
G,
B,
A,
}
impl Default for ChannelName {
fn default() -> Self {
ChannelName::G
}
}
impl fmt::Display for ChannelName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ChannelName::R => write!(f, "R"),
ChannelName::G => write!(f, "G"),
ChannelName::B => write!(f, "B"),
ChannelName::A => write!(f, "A"),
}
}
}
impl FromStr for ChannelName {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_uppercase().as_str() {
"R" => Ok(ChannelName::R),
"G" => Ok(ChannelName::G),
"B" => Ok(ChannelName::B),
"A" => Ok(ChannelName::A),
_ => Err(Error::InvalidAttribute {
name: "channel".to_string(),
message: format!("unknown channel name: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TileStyle {
Wrap,
Mirror,
Clamp,
None,
}
impl Default for TileStyle {
fn default() -> Self {
TileStyle::Wrap
}
}
impl fmt::Display for TileStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TileStyle::Wrap => write!(f, "wrap"),
TileStyle::Mirror => write!(f, "mirror"),
TileStyle::Clamp => write!(f, "clamp"),
TileStyle::None => write!(f, "none"),
}
}
}
impl FromStr for TileStyle {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"wrap" => Ok(TileStyle::Wrap),
"mirror" => Ok(TileStyle::Mirror),
"clamp" => Ok(TileStyle::Clamp),
"none" => Ok(TileStyle::None),
_ => Err(Error::InvalidAttribute {
name: "tilestyleu/tilestylev".to_string(),
message: format!("unknown tile style: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Filter {
Auto,
Linear,
Nearest,
}
impl Default for Filter {
fn default() -> Self {
Filter::Auto
}
}
impl fmt::Display for Filter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Filter::Auto => write!(f, "auto"),
Filter::Linear => write!(f, "linear"),
Filter::Nearest => write!(f, "nearest"),
}
}
}
impl FromStr for Filter {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"auto" => Ok(Filter::Auto),
"linear" => Ok(Filter::Linear),
"nearest" => Ok(Filter::Nearest),
_ => Err(Error::InvalidAttribute {
name: "filter".to_string(),
message: format!("unknown filter type: {}", s),
}),
}
}
}
#[derive(Debug, Clone)]
pub struct NormVectorGroup {
pub id: u32,
pub norm_vectors: Vec<NormVector>,
}
impl NormVectorGroup {
pub fn new(id: u32) -> Self {
Self {
id,
norm_vectors: Vec::new(),
}
}
pub fn add_vector(&mut self, vector: NormVector) -> usize {
let index = self.norm_vectors.len();
self.norm_vectors.push(vector);
index
}
pub fn add_vector_coords(&mut self, x: f64, y: f64, z: f64) -> usize {
self.add_vector(NormVector::new(x, y, z))
}
pub fn vector_count(&self) -> usize {
self.norm_vectors.len()
}
}
#[derive(Debug, Clone, Copy)]
pub struct NormVector {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl NormVector {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
pub fn length(&self) -> f64 {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
pub fn normalize(&self) -> Self {
let len = self.length();
if len > 0.0 {
Self {
x: self.x / len,
y: self.y / len,
z: self.z / len,
}
} else {
*self
}
}
}
#[derive(Debug, Clone)]
pub struct Disp2DGroup {
pub id: u32,
pub disp_id: u32,
pub n_id: u32,
pub height: f64,
pub offset: f64,
pub disp_2d_coords: Vec<Disp2DCoord>,
}
impl Disp2DGroup {
pub fn new(id: u32, disp_id: u32, n_id: u32, height: f64) -> Self {
Self {
id,
disp_id,
n_id,
height,
offset: 0.0,
disp_2d_coords: Vec::new(),
}
}
pub fn set_offset(&mut self, offset: f64) -> &mut Self {
self.offset = offset;
self
}
pub fn add_coord(&mut self, coord: Disp2DCoord) -> usize {
let index = self.disp_2d_coords.len();
self.disp_2d_coords.push(coord);
index
}
pub fn coord_count(&self) -> usize {
self.disp_2d_coords.len()
}
}
#[derive(Debug, Clone, Copy)]
pub struct Disp2DCoord {
pub u: f64,
pub v: f64,
pub n: u32,
pub f: f64,
}
impl Disp2DCoord {
pub fn new(u: f64, v: f64, n: u32) -> Self {
Self {
u,
v,
n,
f: 1.0,
}
}
pub fn with_factor(u: f64, v: f64, n: u32, f: f64) -> Self {
Self { u, v, n, f }
}
}
#[derive(Debug, Clone)]
pub struct DisplacementMesh {
pub vertices: DispVertices,
pub triangles: DispTriangles,
}
impl DisplacementMesh {
pub fn new() -> Self {
Self {
vertices: DispVertices::new(),
triangles: DispTriangles::new(),
}
}
pub fn set_vertices(&mut self, vertices: Vec<DispVertex>) -> &mut Self {
self.vertices.vertices = vertices;
self
}
pub fn set_triangles(&mut self, triangles: Vec<DispTriangle>) -> &mut Self {
self.triangles.triangles = triangles;
self
}
pub fn add_vertex(&mut self, x: f64, y: f64, z: f64) -> u32 {
self.vertices.add_vertex_coords(x, y, z)
}
pub fn add_triangle(&mut self, v1: u32, v2: u32, v3: u32) -> u32 {
self.triangles.add_triangle_indices(v1, v2, v3)
}
pub fn vertex_count(&self) -> usize {
self.vertices.vertex_count()
}
pub fn triangle_count(&self) -> usize {
self.triangles.triangle_count()
}
}
impl Default for DisplacementMesh {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct DispVertices {
pub vertices: Vec<DispVertex>,
}
impl DispVertices {
pub fn new() -> Self {
Self {
vertices: Vec::new(),
}
}
pub fn add_vertex(&mut self, vertex: DispVertex) -> u32 {
let index = self.vertices.len() as u32;
self.vertices.push(vertex);
index
}
pub fn add_vertex_coords(&mut self, x: f64, y: f64, z: f64) -> u32 {
self.add_vertex(DispVertex::new(x, y, z))
}
pub fn vertex_count(&self) -> usize {
self.vertices.len()
}
}
impl Default for DispVertices {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct DispVertex {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl DispVertex {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
}
#[derive(Debug, Clone)]
pub struct DispTriangles {
pub triangles: Vec<DispTriangle>,
pub did: Option<u32>,
}
impl DispTriangles {
pub fn new() -> Self {
Self {
triangles: Vec::new(),
did: None,
}
}
pub fn with_did(did: u32) -> Self {
Self {
triangles: Vec::new(),
did: Some(did),
}
}
pub fn set_did(&mut self, did: u32) -> &mut Self {
self.did = Some(did);
self
}
pub fn get_did(&self) -> Option<u32> {
self.did
}
pub fn add_triangle(&mut self, triangle: DispTriangle) -> u32 {
let index = self.triangles.len() as u32;
self.triangles.push(triangle);
index
}
pub fn add_triangle_indices(&mut self, v1: u32, v2: u32, v3: u32) -> u32 {
self.add_triangle(DispTriangle::new(v1, v2, v3))
}
pub fn triangle_count(&self) -> usize {
self.triangles.len()
}
}
impl Default for DispTriangles {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct DispTriangle {
pub v1: u32,
pub v2: u32,
pub v3: u32,
pub d1: Option<u32>,
pub d2: Option<u32>,
pub d3: Option<u32>,
pub did: Option<u32>,
}
impl DispTriangle {
pub fn new(v1: u32, v2: u32, v3: u32) -> Self {
Self {
v1,
v2,
v3,
d1: None,
d2: None,
d3: None,
did: None,
}
}
pub fn with_did(v1: u32, v2: u32, v3: u32, did: u32) -> Self {
Self {
v1,
v2,
v3,
d1: None,
d2: None,
d3: None,
did: Some(did),
}
}
pub fn set_did(&mut self, did: u32) -> &mut Self {
self.did = Some(did);
self
}
pub fn set_indices(&mut self, d1: u32, d2: u32, d3: u32) -> &mut Self {
self.d1 = Some(d1);
self.d2 = Some(d2);
self.d3 = Some(d3);
self
}
pub fn vertices(&self) -> (u32, u32, u32) {
(self.v1, self.v2, self.v3)
}
}
#[derive(Debug, Clone, Default)]
pub struct DisplacementResources {
pub displacement_2ds: Vec<Displacement2D>,
pub norm_vector_groups: Vec<NormVectorGroup>,
pub disp_2d_groups: Vec<Disp2DGroup>,
}
impl DisplacementResources {
pub fn new() -> Self {
Self::default()
}
pub fn add_displacement_2d(&mut self, disp_2d: Displacement2D) {
self.displacement_2ds.push(disp_2d);
}
pub fn add_norm_vector_group(&mut self, norm_vector_group: NormVectorGroup) {
self.norm_vector_groups.push(norm_vector_group);
}
pub fn add_disp_2d_group(&mut self, disp_2d_group: Disp2DGroup) {
self.disp_2d_groups.push(disp_2d_group);
}
}