Translate avatar and animesh parity tests

This commit is contained in:
2026-08-08 19:43:55 +02:00
parent 7691d54a5d
commit ffe559db61
11 changed files with 2438 additions and 1458 deletions

View File

@@ -2656,7 +2656,7 @@ impl TokenBucket {
}
/// C# type: `T:LibreMetaverse.UUID`.
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct UUID {
bytes: [u8; 16],
}

View File

@@ -0,0 +1,938 @@
#![allow(clippy::float_cmp, clippy::too_many_lines)]
// Exact BSD-3-Clause fixture provenance at LibreMetaverse
// 2aa70bb68513b39795da5d13c88f31b86e85a3ba (see LICENSE.md):
// AnimationTrackTests.cs 9f83830d4278906e4edf8d5ad71d59f96e63ae5860e3b3cc9e191de05741f3d0
// AnimeshPlayerTests.cs b79a4f667c73c30376ee6f550436b26e76efd0fa0383d67bc388a74f07f679ce
// AnimeshSkinningTests.cs 72f51e5dc4fa59e87c150aacb93aae26aabad71fb45e1830cd46e7c5216e1266
// AvatarManagerTests.cs f7547d5caed1d4669eccfad57836f4d2243c8275b1d182e7cb363660b3eabb68
// LindenSkeletonTests.cs 23f7e3ffaf8c4422e8dc2e42ed4223b16175228153aba8eb69cd7ef7e2037b76
use crate::animesh::{AnimationTrack, AnimeshPlayer, JointPose};
use crate::rendering::{
Face, FaceMask, Joint, JointSupportCategory, LindenSkeleton, MeshSkinData, Vertex, VertexWeight,
};
use crate::{AnimeshSkinning, BinBVHAnimationReader, GridClient, PrimitiveTextureEntryFace};
use libremetaverse_types::compat::Object;
use libremetaverse_types::{Error, Matrix4, UUID, Vector2, Vector3};
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
fn random_uuid() -> UUID {
UUID::random().expect("UUID.Random")
}
fn vector3(x: f32, y: f32, z: f32) -> Vector3 {
Vector3::new_with_single_single_single(x, y, z).expect("Vector3 constructor")
}
fn assert_close(actual: f32, expected: f32, tolerance: f32) {
assert!(
(actual - expected).abs() <= tolerance,
"expected {expected} +/- {tolerance}, got {actual}"
);
}
fn make_animation(
in_point: f32,
out_point: f32,
loop_: bool,
ease_in: f32,
ease_out: f32,
) -> BinBVHAnimationReader {
let mut data = Vec::new();
data.extend_from_slice(&1_u16.to_le_bytes());
data.extend_from_slice(&0_u16.to_le_bytes());
data.extend_from_slice(&2_i32.to_le_bytes());
data.extend_from_slice(&(out_point - in_point).to_le_bytes());
data.push(0);
data.extend_from_slice(&in_point.to_le_bytes());
data.extend_from_slice(&out_point.to_le_bytes());
data.extend_from_slice(&i32::from(loop_).to_le_bytes());
data.extend_from_slice(&ease_in.to_le_bytes());
data.extend_from_slice(&ease_out.to_le_bytes());
data.extend_from_slice(&0_u32.to_le_bytes());
data.extend_from_slice(&0_u32.to_le_bytes());
BinBVHAnimationReader::new(data).expect("BinBVHAnimationReader constructor")
}
fn make_track(
in_point: f32,
out_point: f32,
loop_: bool,
ease_in: f32,
ease_out: f32,
) -> AnimationTrack {
let mut track = AnimationTrack::new(random_uuid()).expect("AnimationTrack constructor");
track.set_data(Some(make_animation(
in_point, out_point, loop_, ease_in, ease_out,
)));
track
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.DecodeRotation_ZeroVector_ReturnsIdentity::test fd67db1a9689e3e624fbe8bea98d6278774e4d67f85e611aac6f76105240a6b1 translated
#[test]
fn animation_track_decode_rotation_zero_vector_returns_identity() {
let quaternion = AnimationTrack::decode_rotation(Vector3::zero()).expect("DecodeRotation");
assert_close(quaternion.w, 1.0, 1.0e-5);
assert_close(quaternion.x, 0.0, 1.0e-5);
assert_close(quaternion.y, 0.0, 1.0e-5);
assert_close(quaternion.z, 0.0, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.DecodeRotation_Result_IsNormalized::test 880fdfb75fd9318afa21d3b5296790b3ebad944b43a998a924691fa74efbb2fe translated
#[test]
fn animation_track_decode_rotation_result_is_normalized() {
let vectors = [
vector3(0.1, 0.2, 0.3),
vector3(0.5, 0.0, 0.0),
vector3(0.0, 0.0, 0.99),
Vector3::zero(),
];
for value in vectors {
let quaternion = AnimationTrack::decode_rotation(value).expect("DecodeRotation");
let magnitude = (quaternion.x * quaternion.x
+ quaternion.y * quaternion.y
+ quaternion.z * quaternion.z
+ quaternion.w * quaternion.w)
.sqrt();
assert_close(magnitude, 1.0, 1.0e-5);
}
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.DecodeRotation_WIsRecoveredFromXyz::test 738fd51ea71da85b3b2d43ec30b8e9883b5364c9cbd7c3cbe87de3ea6778daa8 translated
#[test]
fn animation_track_decode_rotation_w_is_recovered_from_xyz() {
let quaternion =
AnimationTrack::decode_rotation(vector3(0.6, 0.0, 0.0)).expect("DecodeRotation");
assert_close(quaternion.x, 0.6, 1.0e-5);
assert_close(quaternion.w, 0.8, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.DecodeRotation_WAlwaysNonNegative::test 679c12e5cdaac7a970f15606229b1843d82e68b28883f87cc5d73567b04c9b57 translated
#[test]
fn animation_track_decode_rotation_w_always_non_negative() {
for value in [
vector3(0.5, 0.5, 0.5),
vector3(-0.5, -0.5, -0.5),
vector3(0.0, 0.0, 0.9),
] {
let quaternion = AnimationTrack::decode_rotation(value).expect("DecodeRotation");
assert!(quaternion.w >= 0.0);
}
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.Advance_WithNullData_DoesNotChangeCurrentTime::test cfd6f6ed1f568fe0dda207cc3222c487a3f8b509a5aa0743109c04032a29b808 translated
#[test]
fn animation_track_advance_with_null_data_does_not_change_current_time() {
let mut track = AnimationTrack::new(random_uuid()).expect("AnimationTrack constructor");
track.advance(1.0).expect("Advance");
assert_eq!(track.current_time(), 0.0);
assert!(!track.is_finished());
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EaseWeight_WithNullData_ReturnsZero::test 7e74e5323ca9870782821a6985f446030d1a8858182bdf82d7718617eacd8ef5 translated
#[test]
fn animation_track_ease_weight_with_null_data_returns_zero() {
let track = AnimationTrack::new(random_uuid()).expect("AnimationTrack constructor");
assert_eq!(track.ease_weight(), 0.0);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EvaluatePose_WithNullData_LeavesEmptyDictionaryUnchanged::test 287210ac2f57c80bd77688a97720b0a7ca63118ce3c8da591274b53aeef88769 translated
#[test]
fn animation_track_evaluate_pose_with_null_data_leaves_empty_dictionary_unchanged() {
let track = AnimationTrack::new(random_uuid()).expect("AnimationTrack constructor");
let mut pose = HashMap::<String, JointPose>::new();
track.evaluate_pose(&mut pose).expect("EvaluatePose");
assert!(pose.is_empty());
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.Advance_NonLooping_BeforeOutPoint_AdvancesTime::test da6ab7efced5ff86e83c320685d6fef33df2a2eb62795206b9f78e87a51ca93d translated
#[test]
fn animation_track_advance_non_looping_before_out_point_advances_time() {
let mut track = make_track(0.0, 10.0, false, 0.0, 0.0);
track.advance(3.0).expect("Advance");
assert_close(track.current_time(), 3.0, 1.0e-5);
assert!(!track.is_finished());
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.Advance_NonLooping_PastOutPoint_ClampsAndSetsFinished::test 02acfe2c10a27a6222e8d222de47255c68afc46ba97cc9319f8239af021fb365 translated
#[test]
fn animation_track_advance_non_looping_past_out_point_clamps_and_sets_finished() {
let mut track = make_track(0.0, 5.0, false, 0.0, 0.0);
track.advance(10.0).expect("Advance");
assert_close(track.current_time(), 5.0, 1.0e-5);
assert!(track.is_finished());
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.Advance_Looping_WrapsAroundToInPoint::test e5e29dec8ece4c3ed19691aa0da0b0199de14902184a91548451c40390af4f8e translated
#[test]
fn animation_track_advance_looping_wraps_around_to_in_point() {
let mut track = make_track(1.0, 4.0, true, 0.0, 0.0);
track.advance(6.0).expect("Advance");
assert_close(track.current_time(), 3.0, 1.0e-4);
assert!(!track.is_finished());
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.Advance_Finished_DoesNotAdvanceFurther::test 17680a41433f4f274645b15f49c4b4f7efea42af4542ee3f6c2e16aa8614f994 translated
#[test]
fn animation_track_advance_finished_does_not_advance_further() {
let mut track = make_track(0.0, 5.0, false, 0.0, 0.0);
track.advance(10.0).expect("Advance");
let stopped_at = track.current_time();
track.advance(5.0).expect("Advance");
assert_eq!(track.current_time(), stopped_at);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EaseWeight_InMiddle_IsOne::test 49a02b2910e60254f80760d40b62b41fc02a4747d85a7b41ee8d082d0352d3cf translated
#[test]
fn animation_track_ease_weight_in_middle_is_one() {
let mut track = make_track(0.0, 10.0, false, 1.0, 1.0);
track.advance(5.0).expect("Advance");
assert_close(track.ease_weight(), 1.0, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EaseWeight_DuringEaseIn_IsFractional::test 419c26af8c1a989a7f99d1b32ca28a41768d7171a4452466f909e1fe61cea186 translated
#[test]
fn animation_track_ease_weight_during_ease_in_is_fractional() {
let mut track = make_track(0.0, 10.0, false, 2.0, 0.0);
track.advance(1.0).expect("Advance");
assert_close(track.ease_weight(), 0.5, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EaseWeight_DuringEaseOut_DecreasesTowardZero::test 18fd883c525f528f0ead69d3df187b106980ff939091c3ad56b156c2d05c91b0 translated
#[test]
fn animation_track_ease_weight_during_ease_out_decreases_toward_zero() {
let mut track = make_track(0.0, 10.0, false, 0.0, 4.0);
track.advance(8.0).expect("Advance");
assert_close(track.ease_weight(), 0.5, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimationTrackTests.cs::AnimationTrackTests.EaseWeight_NoEaseCurves_IsAlwaysOne::test 49421472fcd3dcdb56cb9bb2448b2808bf76757454a67f2ced7524d9a6f89d6e translated
#[test]
fn animation_track_ease_weight_no_ease_curves_is_always_one() {
let mut track = make_track(0.0, 10.0, false, 0.0, 0.0);
track.advance(5.0).expect("Advance");
assert_eq!(track.ease_weight(), 1.0);
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.GetOrAddTrack_CreatesNewTrack::test b7fcdc9f7c02167a6307facaf720390298d68e9c909792d4feab3b78d9b87d7f translated
#[test]
fn animesh_player_get_or_add_track_creates_new_track() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let id = random_uuid();
let track = player.get_or_add_track(id).expect("GetOrAddTrack");
assert!(track.animation_id().equals_with_uuid(id));
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.GetOrAddTrack_SameId_ReturnsSameTrack::test aaec517ee073f26f6ed324cb4391a945221ff0349348bba3757b2378b38df610 translated
#[test]
fn animesh_player_get_or_add_track_same_id_returns_same_track() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let id = random_uuid();
let first = player.get_or_add_track(id).expect("GetOrAddTrack");
let second = player.get_or_add_track(id).expect("GetOrAddTrack");
assert!(Arc::ptr_eq(&first, &second));
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.GetOrAddTrack_DifferentIds_ReturnDifferentTracks::test fe47b6dabc58df9078751501e3bb7e65b0aeb4c0929f4523aded0cb624d64bb1 translated
#[test]
fn animesh_player_get_or_add_track_different_ids_return_different_tracks() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let first = player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
let second = player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
assert!(!Arc::ptr_eq(&first, &second));
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.TrackCount_IncreasesWithNewTracks::test 241b4b3606c0d5c8625701bd21ec41438ac9a410eb11620d1609ddd4d2d58dda translated
#[test]
fn animesh_player_track_count_increases_with_new_tracks() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
assert_eq!(player.track_count(), 2);
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.TrackCount_StableForDuplicateId::test b36dfe47c90dd24fe489ae408cfb299f7214eddb3dc9d5ba42830ab9950d9268 translated
#[test]
fn animesh_player_track_count_stable_for_duplicate_id() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let id = random_uuid();
player.get_or_add_track(id).expect("GetOrAddTrack");
player.get_or_add_track(id).expect("GetOrAddTrack");
assert_eq!(player.track_count(), 1);
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.RetainOnly_RemovesAbsentIds::test d4f15706802d59901e8f07fc17f1d11063b6c182a7a40833d988191edd556f46 translated
#[test]
fn animesh_player_retain_only_removes_absent_ids() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let keep = random_uuid();
let drop = random_uuid();
player.get_or_add_track(keep).expect("GetOrAddTrack");
player.get_or_add_track(drop).expect("GetOrAddTrack");
player
.retain_only(HashSet::from([keep]))
.expect("RetainOnly");
assert_eq!(player.track_count(), 1);
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.RetainOnly_KeepsPresentIds::test eb568b72c8930dea6678a4b54ff2dd47101cef0ed8f6380875cb3fdd27ec6ad2 translated
#[test]
fn animesh_player_retain_only_keeps_present_ids() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
let id = random_uuid();
let original = player.get_or_add_track(id).expect("GetOrAddTrack");
player.retain_only(HashSet::from([id])).expect("RetainOnly");
let retained = player.get_or_add_track(id).expect("GetOrAddTrack");
assert!(Arc::ptr_eq(&original, &retained));
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.RetainOnly_EmptySet_RemovesAllTracks::test 8a8ee666933d4bd920c1d239f5180b9b4ee0d6eb7be67a6965fe29ca6f22edff translated
#[test]
fn animesh_player_retain_only_empty_set_removes_all_tracks() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
player.retain_only(HashSet::new()).expect("RetainOnly");
assert_eq!(player.track_count(), 0);
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.Update_WithNoTracks_DoesNotThrow::test 866542d8e7e14a1f52a4f6b79aa8284cc5347d1a78a44ed9b4950b67078ff592 translated
#[test]
fn animesh_player_update_with_no_tracks_does_not_throw() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
player.update(0.016).expect("Update");
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.Update_WithTracksButNoData_DoesNotThrow::test b29bcf3676a3fca8d1e352ff672350a7bcb92a101dd6f622c53ee2b9a64a3536 translated
#[test]
fn animesh_player_update_with_tracks_but_no_data_does_not_throw() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
player.update(0.016).expect("Update");
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.EvaluatePose_NoLoadedData_ReturnsEmptyDictionary::test 3427b5c94f64a7465a8f3d4d13a1b67e2d002df81a4e736398e1934c8b08cb4b translated
#[test]
fn animesh_player_evaluate_pose_no_loaded_data_returns_empty_dictionary() {
let mut player = AnimeshPlayer::new(random_uuid()).expect("AnimeshPlayer constructor");
player
.get_or_add_track(random_uuid())
.expect("GetOrAddTrack");
let pose = player.evaluate_pose().expect("EvaluatePose");
assert!(pose.is_empty());
}
// parity-case: LibreMetaverse.Tests/AnimeshPlayerTests.cs::AnimeshPlayerTests.ObjectID_StoresConstructorValue::test f2a2efabccbf63c110336cb5785487eb65ee7347e1ff0bb499295e4d5e255654 translated
#[test]
fn animesh_player_object_id_stores_constructor_value() {
let id = random_uuid();
let player = AnimeshPlayer::new(id).expect("AnimeshPlayer constructor");
assert!(player.object_id().equals_with_uuid(id));
}
fn make_joint(name: &str, children: Vec<Joint>) -> Joint {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name(name.to_owned());
joint.set_bone(Some(children));
joint
}
fn make_skeleton(root_name: &str, root_children: Vec<Joint>) -> LindenSkeleton {
let mut skeleton = LindenSkeleton::new().expect("LindenSkeleton constructor");
skeleton.set_bone(make_joint(root_name, root_children));
skeleton
}
fn make_single_joint_skeleton(joint_name: &str) -> LindenSkeleton {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name(joint_name.to_owned());
joint.base.set_pos(vec![0.0, 0.0, 0.0]);
joint.base.set_rot(vec![0.0, 0.0, 0.0]);
let mut skeleton = LindenSkeleton::new().expect("LindenSkeleton constructor");
skeleton.set_bone(joint);
skeleton
}
fn identity_floats() -> Vec<f32> {
vec![
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
]
}
fn make_skin_data(joint_name: &str) -> MeshSkinData {
let mut skin_data = MeshSkinData::new().expect("MeshSkinData constructor");
skin_data.joint_names = vec![joint_name.to_owned()];
skin_data.inverse_bind_matrices = identity_floats();
skin_data.bind_shape_matrix = identity_floats();
skin_data
}
fn assert_matrix_identity(matrix: Matrix4, tolerance: f32) {
let identity = Matrix4::identity();
assert_close(matrix.m11, identity.m11, tolerance);
assert_close(matrix.m12, identity.m12, tolerance);
assert_close(matrix.m13, identity.m13, tolerance);
assert_close(matrix.m14, identity.m14, tolerance);
assert_close(matrix.m21, identity.m21, tolerance);
assert_close(matrix.m22, identity.m22, tolerance);
assert_close(matrix.m23, identity.m23, tolerance);
assert_close(matrix.m24, identity.m24, tolerance);
assert_close(matrix.m31, identity.m31, tolerance);
assert_close(matrix.m32, identity.m32, tolerance);
assert_close(matrix.m33, identity.m33, tolerance);
assert_close(matrix.m34, identity.m34, tolerance);
assert_close(matrix.m41, identity.m41, tolerance);
assert_close(matrix.m42, identity.m42, tolerance);
assert_close(matrix.m43, identity.m43, tolerance);
assert_close(matrix.m44, identity.m44, tolerance);
}
fn vertex(position: Vector3) -> Vertex {
Vertex {
position,
normal: Vector3::zero(),
tex_coord: Vector2::zero(),
}
}
fn face(vertices: Vec<Vertex>, weights: Option<Vec<VertexWeight>>) -> Face {
Face {
begin_s: 0,
begin_t: 0,
center: Vector3::zero(),
edge: Vec::new(),
id: 0,
indices: Vec::new(),
mask: FaceMask(0),
max_extent: Vector3::zero(),
min_extent: Vector3::zero(),
normalized_scale: Vector3::zero(),
num_s: 0,
num_t: 0,
tex_coords1: None,
texture_face: PrimitiveTextureEntryFace,
user_data: Object::from(""),
vertices,
weights,
}
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_NullPose_ThrowsArgumentNullException::test 877768309d784145e02873759fa3726bc2ca6eb4b9d35b0974b98d3c0a06b97a translated
#[test]
fn animesh_skinning_compute_matrices_null_pose_throws_argument_null() {
let skeleton = make_single_joint_skeleton("mRoot");
let skin_data = make_skin_data("mRoot");
let Err(error) =
AnimeshSkinning::compute_skinning_matrices(None, Some(skeleton), Some(skin_data))
else {
panic!("null pose must fail");
};
assert_eq!(error, Error::ArgumentNull);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_NullSkeleton_ThrowsArgumentNullException::test 97d7eef733424588868943400ef2a9664243d5b0c1df884e3cf3e2bc3fa299d6 translated
#[test]
fn animesh_skinning_compute_matrices_null_skeleton_throws_argument_null() {
let pose = HashMap::<String, JointPose>::new();
let skin_data = make_skin_data("mRoot");
let Err(error) = AnimeshSkinning::compute_skinning_matrices(Some(pose), None, Some(skin_data))
else {
panic!("null skeleton must fail");
};
assert_eq!(error, Error::ArgumentNull);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_NullSkinData_ThrowsArgumentNullException::test a0e41b5457d413f4fb8da3d159c74318bf9b74333ce8962612610c862fca8b06 translated
#[test]
fn animesh_skinning_compute_matrices_null_skin_data_throws_argument_null() {
let pose = HashMap::<String, JointPose>::new();
let skeleton = make_single_joint_skeleton("mRoot");
let Err(error) = AnimeshSkinning::compute_skinning_matrices(Some(pose), Some(skeleton), None)
else {
panic!("null skin data must fail");
};
assert_eq!(error, Error::ArgumentNull);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_EmptySkinData_ReturnsEmptyArray::test 412f936f350e1aba601fb736a91087c89976c751a38e1653eec24a958f7c71ba translated
#[test]
fn animesh_skinning_compute_matrices_empty_skin_data_returns_empty_array() {
let pose = HashMap::<String, JointPose>::new();
let skeleton = make_single_joint_skeleton("mRoot");
let mut skin_data = MeshSkinData::new().expect("MeshSkinData constructor");
skin_data.joint_names = Vec::new();
skin_data.inverse_bind_matrices = Vec::new();
let matrices =
AnimeshSkinning::compute_skinning_matrices(Some(pose), Some(skeleton), Some(skin_data))
.expect("ComputeSkinningMatrices");
assert!(matrices.is_empty());
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_JointNotInSkeleton_ProducesIdentity::test c0807fdb1975324c81bda29c46ab84faaad2d19b61b257180f47b6eaa2800146 translated
#[test]
fn animesh_skinning_compute_matrices_joint_not_in_skeleton_produces_identity() {
let pose = HashMap::<String, JointPose>::new();
let skeleton = make_single_joint_skeleton("mRoot");
let skin_data = make_skin_data("nonexistent");
let matrices =
AnimeshSkinning::compute_skinning_matrices(Some(pose), Some(skeleton), Some(skin_data))
.expect("ComputeSkinningMatrices");
assert_eq!(matrices.len(), 1);
assert_matrix_identity(matrices[0], 0.0);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.ComputeSkinningMatrices_IdentitySkeletonAndBindPose_ProducesIdentityMatrix::test 78e0605212c88c8ae33dd68ebe8a3ece75627761f81225b188801dc7ef9e5b32 translated
#[test]
fn animesh_skinning_compute_matrices_identity_skeleton_and_bind_pose_produces_identity() {
let pose = HashMap::<String, JointPose>::new();
let skeleton = make_single_joint_skeleton("mRoot");
let skin_data = make_skin_data("mRoot");
let matrices =
AnimeshSkinning::compute_skinning_matrices(Some(pose), Some(skeleton), Some(skin_data))
.expect("ComputeSkinningMatrices");
assert_eq!(matrices.len(), 1);
assert_matrix_identity(matrices[0], 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.DeformVertices_NullWeights_PassesPositionsThrough::test bbeb45d84770e6b766272bf9a5d48bd415ba98681d9da70d256598429566144d translated
#[test]
fn animesh_skinning_deform_vertices_null_weights_passes_positions_through() {
let face = face(
vec![
vertex(vector3(1.0, 2.0, 3.0)),
vertex(vector3(4.0, 5.0, 6.0)),
],
None,
);
let mut positions = [Vector3::zero(), Vector3::zero()];
AnimeshSkinning::deform_vertices(face, Vec::new(), Matrix4::identity(), &mut positions, None)
.expect("DeformVertices");
assert_eq!(
(positions[0].x, positions[0].y, positions[0].z),
(1.0, 2.0, 3.0)
);
assert_eq!(
(positions[1].x, positions[1].y, positions[1].z),
(4.0, 5.0, 6.0)
);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.DeformVertices_ShortOutputSpan_ThrowsArgumentException::test dfb10b33cedddadbaa5431f1fdf8a1c59369441e94618f97ef13f53ab931907b translated
#[test]
fn animesh_skinning_deform_vertices_short_output_span_throws_argument() {
let face = face(vec![vertex(Vector3::zero()), vertex(Vector3::zero())], None);
let mut positions = [Vector3::zero()];
let Err(error) = AnimeshSkinning::deform_vertices(
face,
Vec::new(),
Matrix4::identity(),
&mut positions,
None,
) else {
panic!("short output span must fail");
};
assert_eq!(error, Error::Argument);
}
// parity-case: LibreMetaverse.Tests/AnimeshSkinningTests.cs::AnimeshSkinningTests.DeformVertices_IdentitySkinning_FullWeight_PreservesPositions::test fcf305a633047e7a4181954fee4990db3537e549f2cb940b08e6d3f0f544c8e1 translated
#[test]
fn animesh_skinning_deform_vertices_identity_skinning_full_weight_preserves_positions() {
let expected = vector3(3.0, 7.0, -2.0);
let face = face(
vec![vertex(expected)],
Some(vec![VertexWeight {
joint0: 0,
joint1: 0,
joint2: 0,
joint3: 0,
weight0: 1.0,
weight1: 0.0,
weight2: 0.0,
weight3: 0.0,
}]),
);
let mut positions = [Vector3::zero()];
AnimeshSkinning::deform_vertices(
face,
vec![Matrix4::identity()],
Matrix4::identity(),
&mut positions,
None,
)
.expect("DeformVertices");
assert_close(positions[0].x, expected.x, 1.0e-5);
assert_close(positions[0].y, expected.y, 1.0e-5);
assert_close(positions[0].z, expected.z, 1.0e-5);
}
// parity-case: LibreMetaverse.Tests/AvatarManagerTests.cs::AvatarManagerTests.RequestOwnAvatarTextures_WhenNotConnected_DoesNotThrow::test bf3539f68a0adc58c2166289ca1c75f6ff03906f71ffe2fb749f6990404b541a translated
#[test]
fn avatar_manager_request_own_avatar_textures_when_not_connected_does_not_throw() {
let client = GridClient::new().expect("GridClient constructor");
client
.avatars()
.request_own_avatar_textures()
.expect("RequestOwnAvatarTextures");
}
// parity-case: LibreMetaverse.Tests/AvatarManagerTests.cs::AvatarManagerTests.UpdateLastReceivedCOFVersion_AcceptsHigherVersion::test 3656364491dcd7a05c868b11ea0d8be48609d10c6054b9696f54cbac10cfe6df translated
#[test]
fn appearance_manager_update_last_received_cof_version_accepts_higher_version() {
let client = GridClient::new().expect("GridClient constructor");
client
.appearance()
.update_last_received_cof_version(3)
.expect("UpdateLastReceivedCOFVersion");
client
.appearance()
.update_last_received_cof_version(8)
.expect("UpdateLastReceivedCOFVersion");
assert_eq!(client.appearance().last_update_received_cof_version(), 8);
}
// parity-case: LibreMetaverse.Tests/AvatarManagerTests.cs::AvatarManagerTests.UpdateLastReceivedCOFVersion_RejectsLowerVersion::test f4a827fcace9d50306a8c375183e056140996d2a39b02e4dd12fc6cc79e5d0f0 translated
#[test]
fn appearance_manager_update_last_received_cof_version_rejects_lower_version() {
let client = GridClient::new().expect("GridClient constructor");
client
.appearance()
.update_last_received_cof_version(10)
.expect("UpdateLastReceivedCOFVersion");
client
.appearance()
.update_last_received_cof_version(4)
.expect("UpdateLastReceivedCOFVersion");
assert_eq!(client.appearance().last_update_received_cof_version(), 10);
}
// parity-case: LibreMetaverse.Tests/AvatarManagerTests.cs::AvatarManagerTests.UpdateLastReceivedCOFVersion_EqualVersion_IsNotAdvanced::test e3db5962cdad5e18ad27a36d0d7cca2d471e96df7513315d0f34bb0db99d723c translated
#[test]
fn appearance_manager_update_last_received_cof_version_equal_version_is_not_advanced() {
let client = GridClient::new().expect("GridClient constructor");
client
.appearance()
.update_last_received_cof_version(6)
.expect("UpdateLastReceivedCOFVersion");
client
.appearance()
.update_last_received_cof_version(6)
.expect("UpdateLastReceivedCOFVersion");
assert_eq!(client.appearance().last_update_received_cof_version(), 6);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_EmptyFilter_ReturnsEmptyList::test 59857e0c12d374a3063e98311f7d262ca9e4fe3bde43af4698d20a6e6e550a64 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_empty_filter_returns_empty_list() {
let skeleton = make_skeleton(
"mPelvis",
vec![make_joint("mTorso", vec![make_joint("mChest", Vec::new())])],
);
let result = skeleton
.build_expanded_joint_list(Box::new(Vec::<String>::new().into_iter()))
.expect("BuildExpandedJointList");
assert!(result.is_empty());
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_NoBoneChildren_ReturnsEmptyList::test c744ad17de5b5dd0e594973181307ddaba0d9b0ecf0ce3ff258e108de45e82be translated
#[test]
fn linden_skeleton_build_expanded_joint_list_no_bone_children_returns_empty_list() {
let mut root = Joint::new().expect("Joint constructor");
root.base.set_name("mPelvis".to_owned());
root.set_bone(None);
let mut skeleton = LindenSkeleton::new().expect("LindenSkeleton constructor");
skeleton.set_bone(root);
let result = skeleton
.build_expanded_joint_list(Box::new(vec!["mPelvis".to_owned()].into_iter()))
.expect("BuildExpandedJointList");
assert!(result.is_empty());
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_LinearChain_AllInFilter_ProducesCorrectSequence::test c2fa9fc02df25cb6eb083746a100abf551d208ea036cadb26a1e94649d33e560 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_linear_chain_all_in_filter() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"A",
vec![make_joint("B", vec![make_joint("C", Vec::new())])],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(["A", "B", "C"].map(str::to_owned).into_iter()))
.expect("BuildExpandedJointList");
assert_eq!(result, vec!["A", "B", "C"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_IntermediateBoneNotInFilter_IsSkippedAsPlaceholder::test 872b6dae196f3700d62b44b6fc3ec50cd41ca78cf36fa3f63d5967b6e1e47bce translated
#[test]
fn linden_skeleton_build_expanded_joint_list_intermediate_not_in_filter_is_skipped() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"A",
vec![make_joint("B", vec![make_joint("C", Vec::new())])],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(["A", "C"].map(str::to_owned).into_iter()))
.expect("BuildExpandedJointList");
assert!(!result.contains(&"B".to_owned()));
assert_eq!(result, vec!["A", "C"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_MultipleConsecutiveIntermediates_AllSkipped::test 033ff727d7f4585321f81b2e4584395bdcbf22ad89eac601be67a1887735f944 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_multiple_intermediates_all_skipped() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"A",
vec![make_joint(
"inter1",
vec![make_joint("inter2", vec![make_joint("B", Vec::new())])],
)],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(["A", "B"].map(str::to_owned).into_iter()))
.expect("BuildExpandedJointList");
assert!(!result.contains(&"inter1".to_owned()));
assert!(!result.contains(&"inter2".to_owned()));
assert_eq!(result, vec!["A", "B"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_BranchingHierarchy_BranchPointRepeatedPerChild::test ff01368c80870ec7d9b4e5eed52bbb3254e8fbf0c06d09f245abf2a450eae6c6 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_branch_point_repeated_per_child() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"A",
vec![
make_joint("B", vec![make_joint("C", Vec::new())]),
make_joint("D", Vec::new()),
],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(
["A", "B", "C", "D"].map(str::to_owned).into_iter(),
))
.expect("BuildExpandedJointList");
assert_eq!(result, vec!["A", "B", "C", "A", "D"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_BranchingWithIntermediates_EffectiveParentUsedForAllBranches::test 5145f5db024a09f833a903f992f42ecc827973f7eddae31a7164e91df0b03ab3 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_branching_uses_effective_parent() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"A",
vec![
make_joint("B", vec![make_joint("C", Vec::new())]),
make_joint("D", Vec::new()),
],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(["A", "C", "D"].map(str::to_owned).into_iter()))
.expect("BuildExpandedJointList");
assert!(!result.contains(&"B".to_owned()));
assert_eq!(result, vec!["A", "C", "A", "D"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_OnlyLeafInFilter_ReachableViaRootPlaceholder::test e4b894c6b0479350e3ef57aab2ccb8d720a7d37df02e09ad4317953804f098fe translated
#[test]
fn linden_skeleton_build_expanded_joint_list_only_leaf_in_filter() {
let skeleton = make_skeleton(
"root",
vec![make_joint(
"inter1",
vec![make_joint("inter2", vec![make_joint("leaf", Vec::new())])],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(vec!["leaf".to_owned()].into_iter()))
.expect("BuildExpandedJointList");
assert_eq!(result, vec!["leaf"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_SingleFilteredDirectChild_ProducesTwoEntries::test f9191747ebd65cf4bbe5b7780400a526f26db86545a08e581348b78f2bf61d18 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_single_filtered_direct_child() {
let skeleton = make_skeleton("root", vec![make_joint("A", Vec::new())]);
let result = skeleton
.build_expanded_joint_list(Box::new(vec!["A".to_owned()].into_iter()))
.expect("BuildExpandedJointList");
assert_eq!(result, vec!["A"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildExpandedJointList_SpineBonesSkipped_DownstreamIndicesNotShifted::test 779aefe6b9fb007f17fed5d2bb6da5d81cf908d938fdceff7c9b155747d5dad9 translated
#[test]
fn linden_skeleton_build_expanded_joint_list_spine_bones_skipped() {
let skeleton = make_skeleton(
"mPelvis",
vec![make_joint(
"mTorso",
vec![make_joint(
"mSpine1",
vec![make_joint(
"mChest",
vec![make_joint("mNeck", vec![make_joint("mHead", Vec::new())])],
)],
)],
)],
);
let result = skeleton
.build_expanded_joint_list(Box::new(
["mTorso", "mChest", "mHead"].map(str::to_owned).into_iter(),
))
.expect("BuildExpandedJointList");
assert!(!result.contains(&"mSpine1".to_owned()));
assert!(!result.contains(&"mNeck".to_owned()));
assert_eq!(result, vec!["mTorso", "mChest", "mHead"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.JointBase_SupportCategory_ReturnsBase_WhenAttributeIsBase::test 809bde18eab918a7ba51c1af1659718ec7f3a7ffc91c3dd8d462b298c78ce968 translated
#[test]
fn joint_base_support_category_returns_base_when_attribute_is_base() {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name("mTorso".to_owned());
joint.base.set_support("base".to_owned());
assert_eq!(joint.base.support_category(), JointSupportCategory::Base);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.JointBase_SupportCategory_ReturnsExtended_WhenAttributeIsExtended::test 47c16fd9e292b4d5de4e28f3b932ef8f7e04e087fd1a0023db3666e85e28762b translated
#[test]
fn joint_base_support_category_returns_extended_when_attribute_is_extended() {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name("mTail1".to_owned());
joint.base.set_support("extended".to_owned());
assert_eq!(
joint.base.support_category(),
JointSupportCategory::Extended
);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.JointBase_SupportCategory_DefaultsToBase_WhenAttributeIsMissing::test 4e5faf4477a615488ac257c511ec1a02c8f53f64e34260fd48af297807dae723 translated
#[test]
fn joint_base_support_category_defaults_to_base_when_attribute_is_missing() {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name("mTest".to_owned());
assert_eq!(joint.base.support_category(), JointSupportCategory::Base);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.Joint_GetAliasesList_ReturnsSplitAliases_WhenAttributeIsSet::test b28dd565d89d53fd1e5f75fa0cc4956661e9ceab65a30290c60d72f619a5e533 translated
#[test]
fn joint_get_aliases_list_returns_split_aliases_when_attribute_is_set() {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name("mPelvis".to_owned());
joint.set_aliases("hip avatar_mPelvis".to_owned());
assert_eq!(
joint.get_aliases_list().expect("GetAliasesList"),
vec!["hip", "avatar_mPelvis"]
);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.Joint_GetAliasesList_ReturnsEmpty_WhenAttributeIsEmpty::test fdab4aa0aafa3739c96c673e974ad89cbdaca458c8f1c0e12a38dd6074b9850a translated
#[test]
fn joint_get_aliases_list_returns_empty_when_attribute_is_empty() {
let mut joint = Joint::new().expect("Joint constructor");
joint.base.set_name("mHead".to_owned());
assert!(joint.get_aliases_list().expect("GetAliasesList").is_empty());
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.GetAllJoints_ReturnsAllJointsDepthFirst::test 93b9b834a8f87acb434c927512fd355e171890afe7a50499f6bed1f7c020d218 translated
#[test]
fn linden_skeleton_get_all_joints_returns_all_joints_depth_first() {
let skeleton = make_skeleton(
"root",
vec![
make_joint("A", vec![make_joint("B", Vec::new())]),
make_joint("C", Vec::new()),
],
);
let names: Vec<String> = skeleton
.get_all_joints()
.expect("GetAllJoints")
.map(|joint| joint.base.name())
.collect();
assert_eq!(names, vec!["root", "A", "B", "C"]);
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.BuildJointDictionary_ContainsCanonicalNamesAndAliases::test d9fd2e8103d19e2c399b0e8a4dd11db2dfd0290bffd678253f64f3c07bd98c24 translated
#[test]
fn linden_skeleton_build_joint_dictionary_contains_names_and_aliases() {
let mut child = Joint::new().expect("Joint constructor");
child.base.set_name("mPelvis".to_owned());
child.set_aliases("hip avatar_mPelvis".to_owned());
let skeleton = make_skeleton("root", vec![child]);
let dictionary = skeleton
.build_joint_dictionary()
.expect("BuildJointDictionary");
assert!(dictionary.contains_key("root"));
assert!(dictionary.contains_key("mPelvis"));
assert!(dictionary.contains_key("hip"));
assert!(dictionary.contains_key("avatar_mPelvis"));
assert!(Arc::ptr_eq(
dictionary.get("hip").expect("hip alias"),
dictionary.get("mPelvis").expect("canonical name")
));
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.GetBone_ReturnsBone_ByCanonicalName::test 87761df2ed95f6dc61a89717a794956faca53a28092464c276406bd777e888a1 translated
#[test]
fn linden_skeleton_get_bone_returns_bone_by_canonical_name() {
let skeleton = make_skeleton("root", vec![make_joint("mTorso", Vec::new())]);
let joint = skeleton
.get_bone("mTorso".to_owned())
.expect("GetBone")
.expect("mTorso joint");
assert_eq!(joint.base.name(), "mTorso");
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.GetBone_ReturnsBone_ByAlias::test 2bad9d7c6ad2b2944537bbf30c89370957f4ce54785c797e0bf234b44aacce2a translated
#[test]
fn linden_skeleton_get_bone_returns_bone_by_alias() {
let mut child = Joint::new().expect("Joint constructor");
child.base.set_name("mPelvis".to_owned());
child.set_aliases("hip".to_owned());
let skeleton = make_skeleton("root", vec![child]);
let joint = skeleton
.get_bone("hip".to_owned())
.expect("GetBone")
.expect("hip alias");
assert_eq!(joint.base.name(), "mPelvis");
}
// parity-case: LibreMetaverse.Tests/LindenSkeletonTests.cs::LindenSkeletonTests.GetBone_ReturnsNull_ForUnknownName::test 19b80d25352f1181a0ccb5e96d068840440dc9352e0e8760ee7774edd414451c translated
#[test]
fn linden_skeleton_get_bone_returns_none_for_unknown_name() {
let skeleton = make_skeleton("root", vec![make_joint("mTorso", Vec::new())]);
assert!(
skeleton
.get_bone("nonexistent".to_owned())
.expect("GetBone")
.is_none()
);
}

View File

@@ -4055,9 +4055,9 @@ pub struct AnimeshSkinning;
impl AnimeshSkinning {
/// C# member: `M:LibreMetaverse.AnimeshSkinning.ComputeSkinningMatrices(System.Collections.Generic.Dictionary{System.String,LibreMetaverse.Animesh.JointPose},LibreMetaverse.Rendering.LindenSkeleton,LibreMetaverse.Rendering.MeshSkinData)`.
pub fn compute_skinning_matrices(
pose: std::collections::HashMap<String, libremetaverse::animesh::JointPose>,
skeleton: libremetaverse::rendering::LindenSkeleton,
skin_data: libremetaverse::rendering::MeshSkinData,
pose: Option<std::collections::HashMap<String, libremetaverse::animesh::JointPose>>,
skeleton: Option<libremetaverse::rendering::LindenSkeleton>,
skin_data: Option<libremetaverse::rendering::MeshSkinData>,
) -> Result<Vec<libremetaverse_types::Matrix4>, crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.AnimeshSkinning.ComputeSkinningMatrices(System.Collections.Generic.Dictionary{System.String,LibreMetaverse.Animesh.JointPose},LibreMetaverse.Rendering.LindenSkeleton,LibreMetaverse.Rendering.MeshSkinData)",
@@ -4068,8 +4068,8 @@ impl AnimeshSkinning {
face: libremetaverse::rendering::Face,
skinning_matrices: Vec<libremetaverse_types::Matrix4>,
bind_shape_matrix: libremetaverse_types::Matrix4,
out_positions: libremetaverse_types::compat::Span<libremetaverse_types::Vector3>,
out_normals: Option<libremetaverse_types::compat::Span<libremetaverse_types::Vector3>>,
out_positions: &mut [libremetaverse_types::Vector3],
out_normals: Option<&mut [libremetaverse_types::Vector3]>,
) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.AnimeshSkinning.DeformVertices(LibreMetaverse.Rendering.Face,LibreMetaverse.Matrix4[],LibreMetaverse.Matrix4,System.Span{LibreMetaverse.Vector3},System.Span{LibreMetaverse.Vector3})",
@@ -4618,7 +4618,10 @@ impl AppearanceManager {
)
}
/// C# member: `M:LibreMetaverse.AppearanceManager.UpdateLastReceivedCOFVersion(System.Int32)`.
pub fn update_last_received_cof_version(&self, cof_version: i32) -> Result<(), crate::Error> {
pub fn update_last_received_cof_version(
&mut self,
cof_version: i32,
) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.AppearanceManager.UpdateLastReceivedCOFVersion(System.Int32)",
)
@@ -28997,7 +29000,7 @@ pub mod animesh {
pub struct AnimationTrack;
impl AnimationTrack {
/// C# member: `M:LibreMetaverse.Animesh.AnimationTrack.Advance(System.Single)`.
pub fn advance(&self, dt: f32) -> Result<(), crate::Error> {
pub fn advance(&mut self, dt: f32) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimationTrack.Advance(System.Single)",
)
@@ -29005,7 +29008,7 @@ pub mod animesh {
/// C# member: `M:LibreMetaverse.Animesh.AnimationTrack.EvaluatePose(System.Collections.Generic.Dictionary{System.String,LibreMetaverse.Animesh.JointPose})`.
pub fn evaluate_pose(
&self,
pose: std::collections::HashMap<String, libremetaverse::animesh::JointPose>,
pose: &mut std::collections::HashMap<String, libremetaverse::animesh::JointPose>,
) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimationTrack.EvaluatePose(System.Collections.Generic.Dictionary{System.String,LibreMetaverse.Animesh.JointPose})",
@@ -29109,7 +29112,7 @@ pub mod animesh {
)
}
/// C# member: `M:LibreMetaverse.Animesh.AnimeshPlayer.Update(System.Single)`.
pub fn update(&self, dt: f32) -> Result<(), crate::Error> {
pub fn update(&mut self, dt: f32) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimeshPlayer.Update(System.Single)",
)
@@ -180601,7 +180604,7 @@ pub mod rendering {
/// C# member: `F:LibreMetaverse.Rendering.Face.Vertices`.
pub vertices: Vec<libremetaverse::rendering::Vertex>,
/// C# member: `F:LibreMetaverse.Rendering.Face.Weights`.
pub weights: Vec<libremetaverse::rendering::VertexWeight>,
pub weights: Option<Vec<libremetaverse::rendering::VertexWeight>>,
}
impl Face {
/// C# member: `M:LibreMetaverse.Rendering.Face.ToString`.
@@ -180769,11 +180772,11 @@ pub mod rendering {
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Rendering.Joint.aliases")
}
/// C# member: `P:LibreMetaverse.Rendering.Joint.bone`.
pub fn bone(&self) -> Vec<libremetaverse::rendering::Joint> {
pub fn bone(&self) -> Option<Vec<libremetaverse::rendering::Joint>> {
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Rendering.Joint.bone")
}
/// Setter for C# member: `P:LibreMetaverse.Rendering.Joint.bone`.
pub fn set_bone(&mut self, value: Vec<libremetaverse::rendering::Joint>) {
pub fn set_bone(&mut self, value: Option<Vec<libremetaverse::rendering::Joint>>) {
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Rendering.Joint.bone")
}
/// C# member: `P:LibreMetaverse.Rendering.Joint.collision_volume`.
@@ -181382,8 +181385,10 @@ pub mod rendering {
/// C# member: `M:LibreMetaverse.Rendering.LindenSkeleton.BuildJointDictionary`.
pub fn build_joint_dictionary(
&self,
) -> Result<std::collections::HashMap<String, libremetaverse::rendering::Joint>, crate::Error>
{
) -> Result<
std::collections::HashMap<String, std::sync::Arc<libremetaverse::rendering::Joint>>,
crate::Error,
> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Rendering.LindenSkeleton.BuildJointDictionary",
)
@@ -181391,8 +181396,10 @@ pub mod rendering {
/// C# member: `M:LibreMetaverse.Rendering.LindenSkeleton.GetAllJoints`.
pub fn get_all_joints(
&self,
) -> Result<Box<dyn Iterator<Item = libremetaverse::rendering::Joint>>, crate::Error>
{
) -> Result<
Box<dyn Iterator<Item = std::sync::Arc<libremetaverse::rendering::Joint>>>,
crate::Error,
> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Rendering.LindenSkeleton.GetAllJoints",
)
@@ -181401,7 +181408,8 @@ pub mod rendering {
pub fn get_bone(
&self,
name_or_alias: String,
) -> Result<Option<libremetaverse::rendering::Joint>, crate::Error> {
) -> Result<Option<std::sync::Arc<libremetaverse::rendering::Joint>>, crate::Error>
{
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Rendering.LindenSkeleton.GetBone(System.String)",
)

View File

@@ -6,6 +6,8 @@ mod generated;
#[cfg(test)]
mod asset_archive_semantics;
#[cfg(test)]
mod avatar_animesh_semantics;
type Terrain = Vec<Vec<f32>>;
type TerrainLoaded = Box<dyn Fn(Terrain, i64, i64) + Send + Sync>;
@@ -25,6 +27,50 @@ impl assets::OarFile {
}
}
#[allow(dead_code)]
impl animesh::AnimationTrack {
fn new(_animation_id: libremetaverse_types::UUID) -> Result<Self, Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimationTrack.#ctor(LibreMetaverse.UUID)",
)
}
fn decode_rotation(
_value: libremetaverse_types::Vector3,
) -> Result<libremetaverse_types::Quaternion, Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimationTrack.DecodeRotation(LibreMetaverse.Vector3)",
)
}
}
#[allow(clippy::unused_self, dead_code)]
impl animesh::AnimeshPlayer {
fn new(_object_id: libremetaverse_types::UUID) -> Result<Self, Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimeshPlayer.#ctor(LibreMetaverse.UUID)",
)
}
fn get_or_add_track(
&mut self,
_animation_id: libremetaverse_types::UUID,
) -> Result<std::sync::Arc<animesh::AnimationTrack>, Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimeshPlayer.GetOrAddTrack(LibreMetaverse.UUID)",
)
}
fn retain_only(
&mut self,
_animation_ids: std::collections::HashSet<libremetaverse_types::UUID>,
) -> Result<(), Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Animesh.AnimeshPlayer.RetainOnly(System.Collections.Generic.ISet{LibreMetaverse.UUID})",
)
}
}
pub use generated::*;
pub use libremetaverse_imaging as imaging_abstractions;
pub use libremetaverse_structured_data as structured_data;