#![allow(clippy::float_cmp, clippy::too_many_arguments, clippy::too_many_lines)]

// Exact BSD-3-Clause fixture provenance at LibreMetaverse
// 2aa70bb68513b39795da5d13c88f31b86e85a3ba (see LICENSE.md):
// ManagedImageTests.cs   9ca15dcbe60b551d14a9716dc8f933f75ae67228d5bf343ea964db9b2725d569
// AvatarBoneMathTests.cs b22c6f685d2275a09748c569db4003c3445f0beba44ee9e01fb03387e4b935de
// MeshFoundryTests.cs    97983bb322cad016134b84e65e30e8eaf761b62efb54ee56f2ebb5f4c5013ca6
// CoordQuatTests.cs      86616de8d717ff994d48fee07532bb2b127bbd92404b75a2631441ca7bf98b6a
// PrimMeshTests.cs       e26d9d9ac99125b705331ccbc3e27f97a93cc9ae0a5d0af90ff0d117c2e8bb53

use libremetaverse::rendering::{
    AvatarBoneMath, BoneTransform, DetailLevel, Joint, LindenSkeleton, Vertex,
};
use libremetaverse::{
    MappingType, Primitive, PrimitiveConstructionData, PrimitiveTextureEntryFace,
};
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
use libremetaverse_prim_mesher::{Coord, PathType, PrimMesh, Quat};
use libremetaverse_rendering_mesh_foundry::MeshFoundry;
use libremetaverse_types::{HoleType, PCode, PathCurve, ProfileCurve, Vector2, Vector3};
use std::collections::HashMap;

fn assert_close(actual: f32, expected: f32, tolerance: f32) {
    assert!(
        (actual - expected).abs() <= tolerance,
        "expected {expected} +/- {tolerance}, got {actual}"
    );
}

fn vector2(x: f32, y: f32) -> Vector2 {
    Vector2 { x, y }
}

fn vector3(x: f32, y: f32, z: f32) -> Vector3 {
    Vector3 { x, y, z }
}

fn prim_mesh(
    sides: i32,
    profile_start: f32,
    profile_end: f32,
    hollow: f32,
    hollow_sides: i32,
    viewer_mode: bool,
    sphere_mode: bool,
    hole_size: Option<(f32, f32)>,
) -> PrimMesh {
    let mut mesh = PrimMesh::new(sides, profile_start, profile_end, hollow, hollow_sides)
        .expect("PrimMesh constructor");
    mesh.viewer_mode = viewer_mode;
    mesh.calc_vertex_normals = viewer_mode;
    mesh.sphere_mode = sphere_mode;
    if let Some((x, y)) = hole_size {
        mesh.hole_size_x = x;
        mesh.hole_size_y = y;
    }
    mesh
}

fn primitive(profile: ProfileCurve, path: PathCurve, path_scale_y: f32) -> Primitive {
    let mut primitive = Primitive::new_with_constructor().expect("Primitive constructor");
    let mut data =
        PrimitiveConstructionData::new_with_constructor().expect("ConstructionData constructor");
    data.p_code = PCode::Prim;
    data.path_curve = path;
    data.set_profile_curve_with_property(profile);
    data.path_scale_x = 1.0;
    data.path_scale_y = path_scale_y;
    data.path_begin = 0.0;
    data.path_end = 1.0;
    data.profile_begin = 0.0;
    data.profile_end = 1.0;
    data.profile_hollow = 0.0;
    data.set_profile_hole(HoleType::Same);
    data.path_revolutions = 1.0;
    primitive.prim_data = data;
    primitive
}

fn multiply(left: [f32; 16], right: [f32; 16]) -> [f32; 16] {
    let mut result = [0.0; 16];
    for row in 0..4 {
        for column in 0..4 {
            result[row * 4 + column] = (0..4)
                .map(|index| left[row * 4 + index] * right[index * 4 + column])
                .sum();
        }
    }
    result
}

fn rotation_y(angle: f32) -> [f32; 16] {
    let (sin, cos) = angle.sin_cos();
    [
        cos, 0.0, -sin, 0.0, 0.0, 1.0, 0.0, 0.0, sin, 0.0, cos, 0.0, 0.0, 0.0, 0.0, 1.0,
    ]
}

fn rotation_z(angle: f32) -> [f32; 16] {
    let (sin, cos) = angle.sin_cos();
    [
        cos, sin, 0.0, 0.0, -sin, cos, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
    ]
}

fn translation(x: f32, y: f32, z: f32) -> [f32; 16] {
    [
        1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0,
    ]
}

fn assert_matrix(actual: &[f32; 16], expected: &[f32; 16]) {
    for index in [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14] {
        assert_close(actual[index], expected[index], 1.0e-4);
    }
}

fn assert_indices_in_range(mesh: &PrimMesh) {
    let count = i32::try_from(mesh.coords.len()).expect("fixture vertex count fits i32");
    for face in &mesh.faces {
        for index in [face.v1, face.v2, face.v3] {
            assert!(
                (0..count).contains(&index),
                "face index {index} out of range"
            );
        }
    }
}

fn vertex(x: f32, y: f32) -> Vertex {
    Vertex {
        position: vector3(0.0, 0.0, 0.0),
        normal: vector3(0.0, 0.0, 1.0),
        tex_coord: vector2(x, y),
    }
}

fn texture_face(repeat: f32) -> PrimitiveTextureEntryFace {
    let mut face = PrimitiveTextureEntryFace::new(None).expect("TextureEntryFace constructor");
    face.set_repeat_u(repeat);
    face.set_repeat_v(repeat);
    face.set_offset_u(0.0);
    face.set_offset_v(0.0);
    face.set_rotation(0.0);
    face.set_tex_map_type(MappingType::Default);
    face
}

// parity-case: LibreMetaverse.Tests/ManagedImageTests.cs::ManagedImageTests.ExportRaw_RGBA_OrderAndFlip::test 76310087f9a87c7c42cb223e6b2da0c6d3bccd1b801f61003f5f8d8fac17d3ab translated
#[test]
fn reviewed_managedimagetests_exportraw_rgba_orderandflip() {
    let mut image = ManagedImage::new(
        2,
        2,
        ManagedImageImageChannels(
            ManagedImageImageChannels::COLOR.0 | ManagedImageImageChannels::ALPHA.0,
        ),
    )
    .expect("ManagedImage constructor");
    image.red = vec![1, 2, 3, 4];
    image.green = vec![10, 20, 30, 40];
    image.blue = vec![100, 110, 120, 130];
    image.alpha = vec![200, 201, 202, 203];

    let raw = image.export_raw().expect("ExportRaw");
    assert_eq!(raw.len(), 16);
    assert_eq!(
        raw,
        vec![
            3, 30, 120, 202, 4, 40, 130, 203, 1, 10, 100, 200, 2, 20, 110, 201,
        ]
    );
}

// parity-case: LibreMetaverse.Tests/ManagedImageTests.cs::ManagedImageTests.ResizeNearestNeighbor_RepeatsSourcePixels::test 54dcfff37e8b4df5351a24bfb3dff1d6cf71e35652a8d4f08029ac98c9178c25 translated
#[test]
fn reviewed_managedimagetests_resizenearestneighbor_repeatssourcepixels() {
    let mut image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR)
        .expect("ManagedImage constructor");
    image.red = vec![1, 2, 3, 4];
    image.green = vec![10, 20, 30, 40];
    image.blue = vec![100, 110, 120, 130];

    image
        .resize_nearest_neighbor(4, 4)
        .expect("ResizeNearestNeighbor");

    assert_eq!(image.width, 4);
    assert_eq!(image.height, 4);
    assert_eq!(image.red.len(), 16);
    assert_eq!(image.red[0], 1);
    assert_eq!(image.red[2], 2);
    assert_eq!(image.red[8], 3);
    assert_eq!(image.red[15], 4);
}

// parity-case: LibreMetaverse.Tests/ManagedImageTests.cs::ManagedImageTests.ConvertChannels_AddsAlphaAndInitializesTo255::test e62e55ecb5bd6908a76f3f33f088b64308eeea5b24dcbc0898bf38452ec79464 translated
#[test]
fn reviewed_managedimagetests_convertchannels_addsalphaandinitializesto255() {
    let mut image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR)
        .expect("ManagedImage constructor");
    image.red = vec![0; 4];
    image.green = vec![0; 4];
    image.blue = vec![0; 4];

    image
        .convert_channels(ManagedImageImageChannels(
            ManagedImageImageChannels::COLOR.0 | ManagedImageImageChannels::ALPHA.0,
        ))
        .expect("ConvertChannels");

    assert_eq!(image.alpha.len(), 4);
    for alpha in image.alpha {
        assert_eq!(alpha, 255);
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/Avatar/AvatarBoneMathTests.cs::AvatarBoneMathTests.BuildBoneWorldMatrices_UnitScale_MatchesNaiveMatrixChain::test 32ea442e98ebfe42238424274aefa960d9bac9a5048c4c971b315b712f870291 translated
#[test]
fn reviewed_avatarbonemathtests_buildboneworldmatrices_unitscale_matchesnaivematrixchain() {
    let mut child = Joint::new().expect("Joint constructor");
    child.base.set_name("Child".into());
    child.base.set_rot(vec![0.0, 15.0, 0.0]);
    let mut root = Joint::new().expect("Joint constructor");
    root.base.set_name("Root".into());
    root.base.set_rot(vec![0.0, 0.0, 30.0]);
    root.set_bone(Some(vec![child]));
    let mut skeleton = LindenSkeleton::new().expect("LindenSkeleton constructor");
    skeleton.set_bone(root);
    let transforms = HashMap::from([
        (
            "Root".into(),
            BoneTransform {
                position: vector3(0.0, 0.0, 1.0),
                scale: vector3(1.0, 1.0, 1.0),
            },
        ),
        (
            "Child".into(),
            BoneTransform {
                position: vector3(0.0, 1.0, 0.0),
                scale: vector3(1.0, 1.0, 1.0),
            },
        ),
    ]);

    let result = AvatarBoneMath::build_bone_world_matrices(skeleton, transforms)
        .expect("BuildBoneWorldMatrices");

    let expected_root = multiply(
        rotation_z(30.0_f32.to_radians()),
        translation(0.0, 0.0, 1.0),
    );
    let child_local = multiply(
        rotation_y(15.0_f32.to_radians()),
        translation(0.0, 1.0, 0.0),
    );
    let expected_child = multiply(child_local, expected_root);
    assert_matrix(&result["Root"].0, &expected_root);
    assert_matrix(&result["Child"].0, &expected_child);
}

// parity-case: LibreMetaverse.Rendering.Tests/Avatar/AvatarBoneMathTests.cs::AvatarBoneMathTests.BuildBoneWorldMatrices_AnisotropicParentScale_OffsetsChildPositionButNotChildScale::test c82d9c6df0612703729e75ec955e4ef90651bb290d3daebe8d8bed7bba8891a3 translated
#[test]
fn reviewed_avatarbonemathtests_buildboneworldmatrices_anisotropicparentscale_offsetschildpositionbutnotchildscale()
 {
    let mut child = Joint::new().expect("Joint constructor");
    child.base.set_name("Child".into());
    child.base.set_rot(vec![0.0, 0.0, 0.0]);
    let mut root = Joint::new().expect("Joint constructor");
    root.base.set_name("Root".into());
    root.base.set_rot(vec![0.0, 0.0, 90.0]);
    root.set_bone(Some(vec![child]));
    let mut skeleton = LindenSkeleton::new().expect("LindenSkeleton constructor");
    skeleton.set_bone(root);
    let transforms = HashMap::from([
        (
            "Root".into(),
            BoneTransform {
                position: vector3(0.0, 0.0, 1.0),
                scale: vector3(1.0, 2.0, 1.0),
            },
        ),
        (
            "Child".into(),
            BoneTransform {
                position: vector3(0.0, 1.0, 0.0),
                scale: vector3(1.0, 1.0, 1.0),
            },
        ),
    ]);

    let result = AvatarBoneMath::build_bone_world_matrices(skeleton, transforms)
        .expect("BuildBoneWorldMatrices");

    let expected_child = multiply(
        rotation_z(std::f32::consts::FRAC_PI_2),
        translation(-2.0, 0.0, 1.0),
    );
    assert_matrix(&result["Child"].0, &expected_child);
    for row in 0..3 {
        let offset = row * 4;
        let length = (result["Child"].0[offset].powi(2)
            + result["Child"].0[offset + 1].powi(2)
            + result["Child"].0[offset + 2].powi(2))
        .sqrt();
        assert_close(length, 1.0, 1.0e-4);
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Box_ReturnsNonNull::test cc5f4d8a21dd21e23e21c6372a4b21e100bffb0fc2a6b9a745d4283c1b05286d translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_box_returnsnonnull() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Box_HasVerticesAndIndices::test 87d09b97a32686ba0183e1a344630480b88da2ef3934f80b6b8b1df55b1bca59 translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_box_hasverticesandindices() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert!(!mesh.vertices.is_empty());
    assert!(!mesh.indices.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Box_AllIndicesInRange::test 2a5360b347d3c21b9b03e1d6afe1bc26d3d6cbe6b5b34f71fe56f277a8dd65be translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_box_allindicesinrange() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert!(
        mesh.indices
            .iter()
            .all(|&index| usize::from(index) < mesh.vertices.len())
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Box_IndicesAreMultipleOfThree::test ac9dc481ea4d448c4c652a0daafb790350f59ea99742945a3f73406b8175d907 translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_box_indicesaremultipleofthree() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert_eq!(mesh.indices.len() % 3, 0);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Cylinder_HasGeometry::test 0a09d750c98f765aa6e391fa9a279527d7d455d5adfcef7f2ce9b84ec87f25f1 translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_cylinder_hasgeometry() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Circle, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert!(!mesh.vertices.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_Torus_HasGeometry::test 0dbd3214721d2bbf601074280d123a9d3cd5928fdf7be637549fc302719f658d translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_torus_hasgeometry() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Circle, PathCurve::Circle, 0.25),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert!(!mesh.vertices.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateSimpleMesh_VertexPositions_AreFinite::test 48de43e7bfcbb7872c7463031fb68e319f600aee7999fbca091332f411054696 translated
#[test]
fn reviewed_meshfoundrytests_generatesimplemesh_vertexpositions_arefinite() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_simple_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateSimpleMesh")
        .expect("simple mesh");
    assert!(mesh.vertices.iter().all(|vertex| {
        vertex.position.x.is_finite()
            && vertex.position.y.is_finite()
            && vertex.position.z.is_finite()
    }));
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_ReturnsNonNull::test 3bcea1aaea9dc511943bb7bdc8ccb0f1020b1a332ea7118cb84548b41acd62b1 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_returnsnonnull() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_Has6Faces::test 518a4fa4591528cfed25be1ae6c102840645300859b565ff475d94053a926d50 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_has6faces() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert_eq!(mesh.faces.len(), 6);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Prism_Has5Faces::test ae62fa75917230768f1f593a911024dc5fdf8e381565520a444ec6b9f83bda01 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_prism_has5faces() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::EqualTriangle, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert_eq!(mesh.faces.len(), 5);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Cylinder_HasAtLeast2Faces::test 7365507988f742db42f88ee719f808464afec2058526d5745c426b2d0104882b translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_cylinder_hasatleast2faces() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Circle, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(mesh.faces.len() >= 2);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Torus_Has1Face::test b5a1e1fcecc24c78fb827b1777e31bd01bf4d668aaa18c61194a98b724fcb271 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_torus_has1face() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Circle, PathCurve::Circle, 0.25),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert_eq!(mesh.faces.len(), 1);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Sphere_HasAtLeast1Face::test 007641edb87e64f199273d2be8049236623470b5c9e14ea2e16726c9da271493 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_sphere_hasatleast1face() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::HalfCircle, PathCurve::Circle, 0.5),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllFaces_HaveVerticesAndIndices::test ac368f766e2c20de2a83b0619a53064a4b801297d042fda88b809caba8a93d75 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_allfaces_haveverticesandindices() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(
        mesh.faces
            .iter()
            .all(|face| !face.vertices.is_empty() && !face.indices.is_empty())
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllFaces_IndicesReferenceValidVertices::test 35babb8108e488dab3b7271b30bfd60e787bdd6109a22dcce5ca89d14c2a7087 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_allfaces_indicesreferencevalidvertices() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(mesh.faces.iter().all(|face| {
        face.indices
            .iter()
            .all(|&index| usize::from(index) < face.vertices.len())
    }));
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_AllFaces_IndicesAreMultipleOfThree::test 5ab7ad852b5477bfa1a11144d16136c21a3479e5de27753ad6d5aa57ca6bf7ce translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_allfaces_indicesaremultipleofthree() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(mesh.faces.iter().all(|face| face.indices.len() % 3 == 0));
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_Normals_AreApproximatelyNormalized::test 6a68dd66ce5b93d406f3ab9fb4d3a70b564a8c788955dcf22a31d58af7cba6e4 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_normals_areapproximatelynormalized() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    for face in &mesh.faces {
        for vertex in &face.vertices {
            let length =
                (vertex.normal.x.powi(2) + vertex.normal.y.powi(2) + vertex.normal.z.powi(2))
                    .sqrt();
            if length > 0.001 {
                assert_close(length, 1.0, 0.01);
            }
        }
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_VertexPositions_AreFinite::test d118c8a8e8c0f7257a35214fc6e7ce6e93136a47ca840aac958929888c743b87 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_vertexpositions_arefinite() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
    assert!(
        mesh.faces
            .iter()
            .flat_map(|face| &face.vertices)
            .all(|vertex| {
                vertex.position.x.is_finite()
                    && vertex.position.y.is_finite()
                    && vertex.position.z.is_finite()
            })
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllLods_ReturnNonNull::case:ca2b46e722de3758 24e8db3f253b95300ab667679c44a82085145a49a83e6aa76d586e9fd0ad8ce1 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_alllods_returnnonnull_22de3758() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::Low,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllLods_ReturnNonNull::case:4ec38c673a800a8e 24e8db3f253b95300ab667679c44a82085145a49a83e6aa76d586e9fd0ad8ce1 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_alllods_returnnonnull_3a800a8e() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::Medium,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllLods_ReturnNonNull::case:1a51d63a985fa00b 24e8db3f253b95300ab667679c44a82085145a49a83e6aa76d586e9fd0ad8ce1 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_alllods_returnnonnull_985fa00b() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::High,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.GenerateFacetedMesh_Box_AllLods_ReturnNonNull::case:204cf13b59ad48dc 24e8db3f253b95300ab667679c44a82085145a49a83e6aa76d586e9fd0ad8ce1 translated
#[test]
fn reviewed_meshfoundrytests_generatefacetedmesh_box_alllods_returnnonnull_59ad48dc() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let _mesh = foundry
        .generate_faceted_mesh(
            primitive(ProfileCurve::Square, PathCurve::Line, 1.0),
            DetailLevel::Highest,
        )
        .expect("GenerateFacetedMesh")
        .expect("faceted mesh");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TransformTexCoords_IdentityTransform_PreservesUVs::test 95670f24bdcc153a7b830f2af25e382b7b8038e03dc8dd459bfe933c0b41c5ca translated
#[test]
fn reviewed_meshfoundrytests_transformtexcoords_identitytransform_preservesuvs() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mut vertices = vec![
        vertex(0.25, 0.75),
        Vertex {
            position: vector3(1.0, 0.0, 0.0),
            normal: vector3(0.0, 0.0, 1.0),
            tex_coord: vector2(0.5, 0.5),
        },
    ];
    let original = [
        vertices[0].tex_coord.x,
        vertices[0].tex_coord.y,
        vertices[1].tex_coord.x,
        vertices[1].tex_coord.y,
    ];
    foundry
        .transform_tex_coords(
            &mut vertices,
            vector3(0.0, 0.0, 0.0),
            texture_face(1.0),
            vector3(1.0, 1.0, 1.0),
        )
        .expect("TransformTexCoords");
    assert_close(vertices[0].tex_coord.x, original[0], 1.0e-4);
    assert_close(vertices[0].tex_coord.y, original[1], 1.0e-4);
    assert_close(vertices[1].tex_coord.x, original[2], 1.0e-4);
    assert_close(vertices[1].tex_coord.y, original[3], 1.0e-4);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TransformTexCoords_Repeat2x_DoublesUVOffset::test 0c4fdd928acec2631aa92b62f4a97d7c9b5b827a2a38337d81ff788ed88ee6e5 translated
#[test]
fn reviewed_meshfoundrytests_transformtexcoords_repeat2x_doublesuvoffset() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mut once = vec![vertex(0.0, 0.0)];
    let mut twice = vec![vertex(0.0, 0.0)];
    foundry
        .transform_tex_coords(
            &mut once,
            vector3(0.0, 0.0, 0.0),
            texture_face(1.0),
            vector3(1.0, 1.0, 1.0),
        )
        .expect("TransformTexCoords repeat 1");
    foundry
        .transform_tex_coords(
            &mut twice,
            vector3(0.0, 0.0, 0.0),
            texture_face(2.0),
            vector3(1.0, 1.0, 1.0),
        )
        .expect("TransformTexCoords repeat 2");
    assert!((twice[0].tex_coord.x - once[0].tex_coord.x).abs() > 1.0e-4);
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TransformTexCoords_EmptyList_DoesNotThrow::test 83f840e2c7a81132feeffa95afcee70e2a5dc1cef0a371256c4ad9b7b4135da3 translated
#[test]
fn reviewed_meshfoundrytests_transformtexcoords_emptylist_doesnotthrow() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mut vertices = Vec::new();
    foundry
        .transform_tex_coords(
            &mut vertices,
            vector3(0.0, 0.0, 0.0),
            texture_face(1.0),
            vector3(1.0, 1.0, 1.0),
        )
        .expect("TransformTexCoords empty list");
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TerrainMesh_FlatHeightmap_HasGeometry::test 39aab46d99eca49810e7b42c1d5a9cfafac8463ddbbdd254b330a59be9e9cd41 translated
#[test]
fn reviewed_meshfoundrytests_terrainmesh_flatheightmap_hasgeometry() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let heights = vec![vec![20.0_f32; 16]; 16];
    let face = foundry
        .terrain_mesh(heights, 0.0, 256.0, 0.0, 256.0)
        .expect("TerrainMesh");
    assert!(!face.vertices.is_empty());
    assert!(!face.indices.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TerrainMesh_AllIndicesInRange::test e0c84f589419729ef68012492da7069fbebc4a16725329e4bf7c34018389e273 translated
#[test]
fn reviewed_meshfoundrytests_terrainmesh_allindicesinrange() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let mut heights = vec![vec![0.0_f32; 16]; 16];
    for (y, row) in heights.iter_mut().enumerate() {
        for (x, height) in row.iter_mut().enumerate() {
            *height = f32::from(u8::try_from(x + y).expect("fixture coordinate"));
        }
    }
    let face = foundry
        .terrain_mesh(heights, 0.0, 256.0, 0.0, 256.0)
        .expect("TerrainMesh");
    assert!(
        face.indices
            .iter()
            .all(|&index| usize::from(index) < face.vertices.len())
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/MeshFoundry/MeshFoundryTests.cs::MeshFoundryTests.TerrainMesh_IndicesAreMultipleOfThree::test 2599d1b5c1732af863ec4201d2f8d99cf8cf59aee2578075fd98ca1ff49e20e3 translated
#[test]
fn reviewed_meshfoundrytests_terrainmesh_indicesaremultipleofthree() {
    let foundry = MeshFoundry::new().expect("MeshFoundry constructor");
    let heights = vec![vec![0.0_f32; 8]; 8];
    let face = foundry
        .terrain_mesh(heights, 0.0, 128.0, 0.0, 128.0)
        .expect("TerrainMesh");
    assert_eq!(face.indices.len() % 3, 0);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Length_KnownVector::test 226d8a4fc384bb2ebbd4819acff2694b2ee9b4fb58b1f6555126be87e631d76b translated
#[test]
fn reviewed_coordtests_coord_length_knownvector() {
    let value = Coord::new(3.0, 4.0, 0.0).expect("Coord constructor");
    assert_close(value.length().expect("Coord Length"), 5.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Length_UnitVector::test 83bc49ca70d01eada674a6c669c2b5f7553e16a8ef0bda2a8eae2dd8b93eec8b translated
#[test]
fn reviewed_coordtests_coord_length_unitvector() {
    let value = Coord::new(1.0, 0.0, 0.0).expect("Coord constructor");
    assert_close(value.length().expect("Coord Length"), 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Normalize_GivesUnitLength::test bc7fa30df7177eebce882f3b6fe28e1b5a1de4f58ef1be0cde0c006a70a57f22 translated
#[test]
fn reviewed_coordtests_coord_normalize_givesunitlength() {
    let mut value = Coord::new(3.0, 4.0, 5.0).expect("Coord constructor");
    let normalized = value.normalize().expect("Coord Normalize");
    assert_close(normalized.length().expect("Coord Length"), 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Normalize_ZeroVector_DoesNotThrow::test 03471b056c8262ed685db3fee6cdce2569672c29ac759eefe049f2c00fcf12a3 translated
#[test]
fn reviewed_coordtests_coord_normalize_zerovector_doesnotthrow() {
    let mut value = Coord::new(0.0, 0.0, 0.0).expect("Coord constructor");
    value.normalize().expect("Coord Normalize");
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Normalize_ZeroVector_GivesZero::test 7aa3f9550bb63091d6815a39feabd9ab2d6986c9529bf1a28298c9d005b850e9 translated
#[test]
fn reviewed_coordtests_coord_normalize_zerovector_giveszero() {
    let mut value = Coord::new(0.0, 0.0, 0.0).expect("Coord constructor");
    let normalized = value.normalize().expect("Coord Normalize");
    assert_close(normalized.x, 0.0, 1.0e-5);
    assert_close(normalized.y, 0.0, 1.0e-5);
    assert_close(normalized.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Cross_XaxisTimesYaxis_GivesZaxis::test a6fd43faa14a5904ecb546d9b21822e85b96945a033cad09e1c22c7a2b95f5a2 translated
#[test]
fn reviewed_coordtests_coord_cross_xaxistimesyaxis_giveszaxis() {
    let x = Coord::new(1.0, 0.0, 0.0).expect("Coord constructor");
    let y = Coord::new(0.0, 1.0, 0.0).expect("Coord constructor");
    let result = Coord::cross(x, y).expect("Coord Cross");
    assert_close(result.x, 0.0, 1.0e-5);
    assert_close(result.y, 0.0, 1.0e-5);
    assert_close(result.z, 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Cross_YaxisTimesXaxis_GivesNegZaxis::test e6732fad351f8948cf1aa20d39482f2ff40c4866d465f76237878f0aead4c201 translated
#[test]
fn reviewed_coordtests_coord_cross_yaxistimesxaxis_givesnegzaxis() {
    let x = Coord::new(1.0, 0.0, 0.0).expect("Coord constructor");
    let y = Coord::new(0.0, 1.0, 0.0).expect("Coord constructor");
    let result = Coord::cross(y, x).expect("Coord Cross");
    assert_close(result.z, -1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::CoordTests.Coord_Add_IsCommutative::test 77c274254e338314aa953a6b4efad70c5a16b1ca556be8cf6bb22cbe74fe32d2 translated
#[test]
fn reviewed_coordtests_coord_add_iscommutative() {
    let a = Coord::new(1.0, 2.0, 3.0).expect("Coord constructor");
    let b = Coord::new(4.0, 5.0, 6.0).expect("Coord constructor");
    let ab = Coord::add(a, b);
    let ba = Coord::add(
        Coord::new(4.0, 5.0, 6.0).expect("Coord constructor"),
        Coord::new(1.0, 2.0, 3.0).expect("Coord constructor"),
    );
    assert_close(ab.x, ba.x, 1.0e-5);
    assert_close(ab.y, ba.y, 1.0e-5);
    assert_close(ab.z, ba.z, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Quat_AxisAngle_IsNormalized::test a6e9d0063560fe81c1f1fd9741ba13446453618a2847c32e7ae9a38d2cf68633 translated
#[test]
fn reviewed_quattests_quat_axisangle_isnormalized() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    assert_close(quaternion.length().expect("Quat Length"), 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Quat_Identity_RotatesCoordUnchanged::test ef48a7907ee3a89fef6f6657667fe777eca9e3a006c828e127dd69bc456ab22b translated
#[test]
fn reviewed_quattests_quat_identity_rotatescoordunchanged() {
    let quaternion =
        Quat::new_with_single_single_single_single(0.0, 0.0, 0.0, 1.0).expect("Quat constructor");
    let value = Coord::new(1.0, 2.0, 3.0).expect("Coord constructor");
    let result = Coord::mul_with_coord_quat(value, quaternion);
    assert_close(result.x, 1.0, 1.0e-5);
    assert_close(result.y, 2.0, 1.0e-5);
    assert_close(result.z, 3.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_90DegAroundXaxis_YbecomesZ::test cb99be74f6d15d6bbb890cd364f57bb872a4b075dc1115c0180d3b7bda82aca2 translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_90degaroundxaxis_ybecomesz() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let result = Coord::mul_with_coord_quat(
        Coord::new(0.0, 1.0, 0.0).expect("Coord constructor"),
        quaternion,
    );
    assert_close(result.x, 0.0, 1.0e-5);
    assert_close(result.y, 0.0, 1.0e-5);
    assert_close(result.z, 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_90DegAroundXaxis_ZbecomesNegY_BugRegression::test 091d344b5e577391f8e94d86d7507ec9089460241d309e5cbd7d1abc5556d3aa translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_90degaroundxaxis_zbecomesnegy_bugregression() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let result = Coord::mul_with_coord_quat(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        quaternion,
    );
    assert_close(result.x, 0.0, 1.0e-5);
    assert_close(result.y, -1.0, 1.0e-5);
    assert_close(result.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_90DegAroundZaxis_XbecomesY::test aa03d22621c46a26ff819e0cfe19d9daab7a9e270144af583faea35081461b0a translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_90degaroundzaxis_xbecomesy() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let result = Coord::mul_with_coord_quat(
        Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"),
        quaternion,
    );
    assert_close(result.x, 0.0, 1.0e-5);
    assert_close(result.y, 1.0, 1.0e-5);
    assert_close(result.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_90DegAroundYaxis_ZbecomesX::test 40394936517b6730795407b515c56e010589e849ffecf3edb4fa40c768ab4b59 translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_90degaroundyaxis_zbecomesx() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(0.0, 1.0, 0.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let result = Coord::mul_with_coord_quat(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        quaternion,
    );
    assert_close(result.x, 1.0, 1.0e-5);
    assert_close(result.y, 0.0, 1.0e-5);
    assert_close(result.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_180DegAroundZaxis_NegatesXandY::test a666e902349890956adcd8212f0ab1aa58afe4e029ed2ea0e6e2709be9db753f translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_180degaroundzaxis_negatesxandy() {
    let quaternion = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::PI,
    )
    .expect("Quat axis-angle constructor");
    let result = Coord::mul_with_coord_quat(
        Coord::new(1.0, 1.0, 0.0).expect("Coord constructor"),
        quaternion,
    );
    assert_close(result.x, -1.0, 1.0e-5);
    assert_close(result.y, -1.0, 1.0e-5);
    assert_close(result.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Coord_RotateByQuat_PreservesLength::test 2366403c8ea2beda7461e01afc9297376839920cac5593af3994a4f46e0f5687 translated
#[test]
fn reviewed_quattests_coord_rotatebyquat_preserveslength() {
    let mut axis = Coord::new(1.0, 1.0, 1.0).expect("Coord constructor");
    let quaternion = Quat::new_with_coord_single(
        axis.normalize().expect("Coord Normalize"),
        std::f32::consts::PI / 3.0,
    )
    .expect("Quat axis-angle constructor");
    let value = Coord::new(3.0, 4.0, 5.0).expect("Coord constructor");
    let original = value.length().expect("Coord Length");
    let result = Coord::mul_with_coord_quat(value, quaternion);
    assert_close(result.length().expect("Coord Length"), original, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Quat_Multiply_TwoNineties_AroundZ_Gives180::test bdaaf2ad06bcf2f696cf5bfb470680fb69eb27a48dec461049d53efeb2423f6d translated
#[test]
fn reviewed_quattests_quat_multiply_twonineties_aroundz_gives180() {
    let q90 = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let q90_again = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_2,
    )
    .expect("Quat axis-angle constructor");
    let q180 = Quat::mul(q90, q90_again);
    let result =
        Coord::mul_with_coord_quat(Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"), q180);
    assert_close(result.x, -1.0, 1.0e-5);
    assert_close(result.y, 0.0, 1.0e-5);
    assert_close(result.z, 0.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/CoordQuatTests.cs::QuatTests.Quat_Multiply_IsAssociative::test 8914e770bcbeb414a96bfc1d4316dcc1b96ff367f6b16eec46ed84ddcd31175f translated
#[test]
fn reviewed_quattests_quat_multiply_isassociative() {
    let q1 = Quat::new_with_coord_single(
        Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_4,
    )
    .expect("Quat axis-angle constructor");
    let q2 = Quat::new_with_coord_single(
        Coord::new(0.0, 1.0, 0.0).expect("Coord constructor"),
        std::f32::consts::PI / 3.0,
    )
    .expect("Quat axis-angle constructor");
    let q3 = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::PI / 6.0,
    )
    .expect("Quat axis-angle constructor");
    let result1 = Coord::mul_with_coord_quat(
        Coord::new(1.0, 2.0, 3.0).expect("Coord constructor"),
        Quat::mul(q1, Quat::mul(q2, q3)),
    );
    let q1_again = Quat::new_with_coord_single(
        Coord::new(1.0, 0.0, 0.0).expect("Coord constructor"),
        std::f32::consts::FRAC_PI_4,
    )
    .expect("Quat axis-angle constructor");
    let q2_again = Quat::new_with_coord_single(
        Coord::new(0.0, 1.0, 0.0).expect("Coord constructor"),
        std::f32::consts::PI / 3.0,
    )
    .expect("Quat axis-angle constructor");
    let q3_again = Quat::new_with_coord_single(
        Coord::new(0.0, 0.0, 1.0).expect("Coord constructor"),
        std::f32::consts::PI / 6.0,
    )
    .expect("Quat axis-angle constructor");
    let result2 = Coord::mul_with_coord_quat(
        Coord::new(1.0, 2.0, 3.0).expect("Coord constructor"),
        Quat::mul(Quat::mul(q1_again, q2_again), q3_again),
    );
    assert_close(result1.x, result2.x, 1.0e-5);
    assert_close(result1.y, result2.y, 1.0e-5);
    assert_close(result1.z, result2.z, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_Linear_HasVerticesAndFaces::test a52196d3b6aa8cfebf064db9b0a5b99cd41786b171ad69db2adad7dbcfafb475 translated
#[test]
fn reviewed_primmeshtests_extrude_box_linear_hasverticesandfaces() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_Linear_AllFaceIndicesInRange::test 91b9461e9522719f9ed105fa49c43b914b7b36509633dce55230d7df2c608569 translated
#[test]
fn reviewed_primmeshtests_extrude_box_linear_allfaceindicesinrange() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert_indices_in_range(&mesh);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Cylinder_Linear_HasGeometry::test d4b9d89e7dbebde42517a2d3f35b9c5951e3ec7a0b1a0551739ca11d6cd2bacc translated
#[test]
fn reviewed_primmeshtests_extrude_cylinder_linear_hasgeometry() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Prism_Linear_HasGeometry::test a9087a5d72cf9940aae5a924e65c5a0c2b673b3aede678418458ffc13f4550c5 translated
#[test]
fn reviewed_primmeshtests_extrude_prism_linear_hasgeometry() {
    let mut mesh = prim_mesh(3, 0.0, 1.0, 0.0, 3, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Torus_Circular_HasGeometry::test 27f2209c1b96aad8f096ecb256ae4cdc6e787284923b3a76cf22fed3457931a8 translated
#[test]
fn reviewed_primmeshtests_extrude_torus_circular_hasgeometry() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, false, false, Some((1.0, 0.25)));
    mesh.extrude(PathType::Circular).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Torus_Circular_AllFaceIndicesInRange::test d1f2082c714780a69926d53005b2699f336aab1e3fa8f9b5765d19434f7cf5f6 translated
#[test]
fn reviewed_primmeshtests_extrude_torus_circular_allfaceindicesinrange() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, false, false, Some((1.0, 0.25)));
    mesh.extrude(PathType::Circular).expect("PrimMesh Extrude");
    assert_indices_in_range(&mesh);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_WithHollow_HasGeometry::test ec5385d0219bf67df7dce55812d5850b04403f2727851a73308b9e5e5c0c8d80 translated
#[test]
fn reviewed_primmeshtests_extrude_box_withhollow_hasgeometry() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.5, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_WithProfileCut_HasGeometry::test b97ae456815aa05110f8c1bf345a789040faf72a05a6991922fecafc181ec0f8 translated
#[test]
fn reviewed_primmeshtests_extrude_box_withprofilecut_hasgeometry() {
    let mut mesh = prim_mesh(4, 0.1, 0.9, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_ViewerMode_HasViewerFaces::test 00fe2f345e1e76efb79a110c51c12ef866196f601a5cbfdfac5a170a1c7aace2 translated
#[test]
fn reviewed_primmeshtests_extrude_box_viewermode_hasviewerfaces() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(!mesh.viewer_faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_ViewerMode_AllViewerFaceVerticesFinite::test b1e9048351aa655fd98780329c15378dd0700113b395daf5a6aab88a1f23a291 translated
#[test]
fn reviewed_primmeshtests_extrude_box_viewermode_allviewerfaceverticesfinite() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    for face in &mesh.viewer_faces {
        for vertex in [&face.v1, &face.v2, &face.v3] {
            assert!(vertex.x.is_finite());
            assert!(vertex.y.is_finite());
            assert!(vertex.z.is_finite());
        }
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Box_ViewerMode_NumPrimFaces_Is6::test 4950fd4921f79d2dd8a5c1d85a75a3e92c45eb8fb6d370af83e535b0ecb87e36 translated
#[test]
fn reviewed_primmeshtests_extrude_box_viewermode_numprimfaces_is6() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("GetVertexIndexer")
        .expect("viewer-mode VertexIndexer");
    assert_eq!(indexer.num_prim_faces, 6);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Cylinder_ViewerMode_NumPrimFaces_AtLeast2::test e7ce8cebe702b2da2236270511c6e5e21c7d6cb9cb799fff66c344671249a700 translated
#[test]
fn reviewed_primmeshtests_extrude_cylinder_viewermode_numprimfaces_atleast2() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("GetVertexIndexer")
        .expect("viewer-mode VertexIndexer");
    assert!(indexer.num_prim_faces >= 2);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Torus_ViewerMode_NumPrimFaces_Is1::test e6c6a7f5280df49679ebbfad4b8ccb0b632928127bc6c853d0ba8f91b0f2d5b9 translated
#[test]
fn reviewed_primmeshtests_extrude_torus_viewermode_numprimfaces_is1() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, true, false, Some((1.0, 0.25)));
    mesh.extrude(PathType::Circular).expect("PrimMesh Extrude");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("GetVertexIndexer")
        .expect("viewer-mode VertexIndexer");
    assert_eq!(indexer.num_prim_faces, 1);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Sphere_ViewerMode_NumPrimFaces_Is1::test 0c382dece7dd5dcbfffda989282f9dbea3993ab98552bc010731287c2c74e9aa translated
#[test]
fn reviewed_primmeshtests_extrude_sphere_viewermode_numprimfaces_is1() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, true, true, Some((1.0, 0.5)));
    mesh.extrude(PathType::Circular).expect("PrimMesh Extrude");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("GetVertexIndexer")
        .expect("viewer-mode VertexIndexer");
    assert_eq!(indexer.num_prim_faces, 1);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Extrude_Torus_ViewerMode_HasViewerFaces::test bdcb545c23f6cf2fb493d52ffaa080456cacce9fd76de7d103522b28a9c9a7fa translated
#[test]
fn reviewed_primmeshtests_extrude_torus_viewermode_hasviewerfaces() {
    let mut mesh = prim_mesh(24, 0.0, 1.0, 0.0, 4, true, false, Some((1.0, 0.25)));
    mesh.extrude(PathType::Circular).expect("PrimMesh Extrude");
    assert!(!mesh.viewer_faces.is_empty());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.CalcNormals_Box_ProducesOneNormalPerFace::test fa447f9bed75300d0af988a149d60fcf91bf24522c470f64915f0b9aa438fe63 translated
#[test]
fn reviewed_primmeshtests_calcnormals_box_producesonenormalperface() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    mesh.calc_normals().expect("CalcNormals");
    assert_eq!(mesh.normals.len(), mesh.faces.len());
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.CalcNormals_Box_AllNonZeroNormalsUnitLength::test baab4a2688ab5a0459cbf258a3501e7f111da0f830ba23ee267cf5c1e76f0fd3 translated
#[test]
fn reviewed_primmeshtests_calcnormals_box_allnonzeronormalsunitlength() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    mesh.calc_normals().expect("CalcNormals");
    for normal in &mesh.normals {
        let length = normal.length().expect("Coord Length");
        if length > 0.001 {
            assert_close(length, 1.0, 1.0e-5);
        }
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.CalcNormals_CalledTwice_IsIdempotent::test f7648170eb671abb0e6321816ab5afe2e2f20dc811c1bb4cdc7de1f2b9fb8942 translated
#[test]
fn reviewed_primmeshtests_calcnormals_calledtwice_isidempotent() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    mesh.calc_normals().expect("CalcNormals");
    let count = mesh.normals.len();
    mesh.calc_normals().expect("CalcNormals");
    assert_eq!(mesh.normals.len(), count);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.VertexIndexer_Box_IsNotNull::test 78001c5d1ddcdeb4c87e2eadcc7091c022295832ba597f8355f25fb9a4545f41 translated
#[test]
fn reviewed_primmeshtests_vertexindexer_box_isnotnull() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(
        mesh.get_vertex_indexer()
            .expect("GetVertexIndexer")
            .is_some()
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.VertexIndexer_NonViewerMode_ReturnsNull::test 3e5dba3fe5daae3610da08d6eedb24bf7dcf72234926b5ce646d295a4f5cf1e9 translated
#[test]
fn reviewed_primmeshtests_vertexindexer_nonviewermode_returnsnull() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    assert!(
        mesh.get_vertex_indexer()
            .expect("GetVertexIndexer")
            .is_none()
    );
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.VertexIndexer_Box_AllPolygonIndicesInRange::test 9f3ba161d189d48b2301a96d8ca03ad280ff4cc5e84ffdcca6f76618a1ff6df9 translated
#[test]
fn reviewed_primmeshtests_vertexindexer_box_allpolygonindicesinrange() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, true, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("GetVertexIndexer")
        .expect("viewer-mode VertexIndexer");
    for face_index in 0..usize::try_from(indexer.num_prim_faces).expect("face count") {
        let vertices = &indexer.viewer_vertices[face_index];
        if let Some(polygons) = &indexer.viewer_polygons[face_index] {
            let vertex_count = i32::try_from(vertices.len()).expect("vertex count");
            for polygon in polygons {
                for index in [polygon.v1, polygon.v2, polygon.v3] {
                    assert!((0..vertex_count).contains(&index));
                }
            }
        }
    }
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Copy_Box_ProducesIndependentInstance::test 5c29d2359d178323cc9e7498db0cea3d02ac7a83e1226f49e56fe0eb1034edbc translated
#[test]
fn reviewed_primmeshtests_copy_box_producesindependentinstance() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let mut copy = mesh.copy().expect("PrimMesh Copy");
    assert_eq!(copy.coords.len(), mesh.coords.len());
    assert_eq!(copy.faces.len(), mesh.faces.len());
    copy.add_pos(1.0, 0.0, 0.0).expect("PrimMesh AddPos");
    assert_ne!(mesh.coords[0].x, copy.coords[0].x);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.AddPos_ShiftsAllCoords::test 6e6c6e49ecb2661bcb52046e45cc5b6fb9bd3585521531077eebca304c38339e translated
#[test]
fn reviewed_primmeshtests_addpos_shiftsallcoords() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let original = mesh.coords[0].x;
    mesh.add_pos(10.0, 0.0, 0.0).expect("PrimMesh AddPos");
    assert_close(mesh.coords[0].x, original + 10.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.Scale_ScalesAllCoords::test 01e9bb40a4c96cd5bb781a05d39f2a15d36a4899e4f0228e9623ba5fd1ec3b6d translated
#[test]
fn reviewed_primmeshtests_scale_scalesallcoords() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let original = mesh.coords[0].x;
    mesh.scale(2.0, 2.0, 2.0).expect("PrimMesh Scale");
    assert_close(mesh.coords[0].x, original * 2.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.AddRot_ByIdentity_DoesNotChangeCoords::test ef73dd9d3fee6f8f2c7bfeb462bb6bc864b3f47f3a688ab6892cc49fc8fe7fe9 translated
#[test]
fn reviewed_primmeshtests_addrot_byidentity_doesnotchangecoords() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let original = [mesh.coords[0].x, mesh.coords[0].y, mesh.coords[0].z];
    mesh.add_rot(
        Quat::new_with_single_single_single_single(0.0, 0.0, 0.0, 1.0).expect("Quat constructor"),
    )
    .expect("PrimMesh AddRot");
    assert_close(mesh.coords[0].x, original[0], 1.0e-5);
    assert_close(mesh.coords[0].y, original[1], 1.0e-5);
    assert_close(mesh.coords[0].z, original[2], 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.SurfaceNormal_Box_FirstFace_IsUnitLength::test 5b5b4b33300b056c12b8e249ec27abf7ba174e5db524542ab1316c8583b1c8f6 translated
#[test]
fn reviewed_primmeshtests_surfacenormal_box_firstface_isunitlength() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    let normal = mesh.surface_normal(0).expect("SurfaceNormal");
    assert_close(normal.length().expect("Coord Length"), 1.0, 1.0e-5);
}

// parity-case: LibreMetaverse.Rendering.Tests/PrimMesher/PrimMeshTests.cs::PrimMeshTests.SurfaceNormal_InvalidIndex_Throws::test cc1b305dd2d03589ccc1899dc8ad5c3ea8ca05d451e0a41e5ea2c0a4d85c405c translated
#[test]
fn reviewed_primmeshtests_surfacenormal_invalidindex_throws() {
    let mut mesh = prim_mesh(4, 0.0, 1.0, 0.0, 4, false, false, None);
    mesh.extrude(PathType::Linear).expect("PrimMesh Extrude");
    match mesh.surface_normal(-1) {
        Err(libremetaverse_prim_mesher::Error::IndexOutOfRange) => {}
        Err(error) => panic!("expected IndexOutOfRange, got {error:?}"),
        Ok(_) => panic!("expected IndexOutOfRange"),
    }
    match mesh.surface_normal(i32::try_from(mesh.faces.len()).expect("face count")) {
        Err(libremetaverse_prim_mesher::Error::IndexOutOfRange) => {}
        Err(error) => panic!("expected IndexOutOfRange, got {error:?}"),
        Ok(_) => panic!("expected IndexOutOfRange"),
    }
}
