use crate::error::Result;
use crate::extension::ExtensionHandler;
use crate::model::{Extension, Model};
use crate::validator;
pub struct DisplacementExtensionHandler;
impl ExtensionHandler for DisplacementExtensionHandler {
fn extension_type(&self) -> Extension {
Extension::Displacement
}
fn validate(&self, model: &Model) -> Result<()> {
validator::validate_displacement_extension(model)
}
fn is_used_in_model(&self, model: &Model) -> bool {
!model.resources.displacement_maps.is_empty()
|| !model.resources.norm_vector_groups.is_empty()
|| !model.resources.disp2d_groups.is_empty()
|| model
.resources
.objects
.iter()
.any(|obj| obj.displacement_mesh.is_some())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::{
Disp2DCoords, Disp2DGroup, Displacement2D, DisplacementMesh, DisplacementTriangle,
NormVector, NormVectorGroup, Object, Vertex,
};
#[test]
fn test_extension_type() {
let handler = DisplacementExtensionHandler;
assert_eq!(handler.extension_type(), Extension::Displacement);
}
#[test]
fn test_namespace() {
let handler = DisplacementExtensionHandler;
assert_eq!(
handler.namespace(),
"http://schemas.microsoft.com/3dmanufacturing/displacement/2022/07"
);
}
#[test]
fn test_name() {
let handler = DisplacementExtensionHandler;
assert_eq!(handler.name(), "Displacement");
}
#[test]
fn test_is_used_in_model_empty() {
let handler = DisplacementExtensionHandler;
let model = Model::new();
assert!(!handler.is_used_in_model(&model));
}
#[test]
fn test_is_used_in_model_with_displacement_map() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model
.resources
.displacement_maps
.push(Displacement2D::new(1, "/3D/Textures/disp.png".to_string()));
assert!(handler.is_used_in_model(&model));
}
#[test]
fn test_is_used_in_model_with_norm_vector_group() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model
.resources
.norm_vector_groups
.push(NormVectorGroup::new(1));
assert!(handler.is_used_in_model(&model));
}
#[test]
fn test_is_used_in_model_with_disp2d_group() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model
.resources
.disp2d_groups
.push(Disp2DGroup::new(1, 10, 20, 1.0));
assert!(handler.is_used_in_model(&model));
}
#[test]
fn test_is_used_in_model_with_displacement_mesh() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
let mut obj = Object::new(1);
let mut displacement_mesh = DisplacementMesh::new();
displacement_mesh.vertices.push(Vertex::new(0.0, 0.0, 0.0));
displacement_mesh.vertices.push(Vertex::new(1.0, 0.0, 0.0));
displacement_mesh.vertices.push(Vertex::new(0.0, 1.0, 0.0));
displacement_mesh.vertices.push(Vertex::new(0.0, 0.0, 1.0));
displacement_mesh
.triangles
.push(DisplacementTriangle::new(0, 1, 2));
displacement_mesh
.triangles
.push(DisplacementTriangle::new(0, 1, 3));
displacement_mesh
.triangles
.push(DisplacementTriangle::new(0, 2, 3));
displacement_mesh
.triangles
.push(DisplacementTriangle::new(1, 2, 3));
obj.displacement_mesh = Some(displacement_mesh);
model.resources.objects.push(obj);
assert!(handler.is_used_in_model(&model));
}
#[test]
fn test_validate_empty_model() {
let handler = DisplacementExtensionHandler;
let model = Model::new();
assert!(handler.validate(&model).is_ok());
}
#[test]
fn test_validate_with_valid_displacement_resources() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model.required_extensions.push(Extension::Displacement);
model
.resources
.displacement_maps
.push(Displacement2D::new(1, "/3D/Textures/disp.png".to_string()));
let mut norm_group = NormVectorGroup::new(2);
norm_group.vectors.push(NormVector::new(0.0, 0.0, 1.0));
model.resources.norm_vector_groups.push(norm_group);
let mut disp_group = Disp2DGroup::new(3, 1, 2, 1.0);
disp_group.coords.push(Disp2DCoords::new(0.0, 0.0, 0));
model.resources.disp2d_groups.push(disp_group);
assert!(handler.validate(&model).is_ok());
}
#[test]
fn test_validate_missing_extension_declaration() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model
.resources
.displacement_maps
.push(Displacement2D::new(1, "/3D/Textures/disp.png".to_string()));
let result = handler.validate(&model);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("displacement extension is not declared"));
}
#[test]
fn test_validate_invalid_path() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model.required_extensions.push(Extension::Displacement);
model
.resources
.displacement_maps
.push(Displacement2D::new(1, "/invalid/path.png".to_string()));
let result = handler.validate(&model);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("not in /3D/Textures/"));
}
#[test]
fn test_validate_invalid_reference() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
model.required_extensions.push(Extension::Displacement);
let disp_group = Disp2DGroup::new(1, 999, 888, 1.0); model.resources.disp2d_groups.push(disp_group);
let result = handler.validate(&model);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("non-existent"));
}
#[test]
fn test_default_post_parse() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
assert!(handler.post_parse(&mut model).is_ok());
}
#[test]
fn test_default_pre_write() {
let handler = DisplacementExtensionHandler;
let mut model = Model::new();
assert!(handler.pre_write(&mut model).is_ok());
}
}