Some checks failed
Native code generation / deterministic (push) Failing after 1m48s
Imaging and meshing gate / native (push) Successful in 5m26s
JPEG 2000 feature / linux (push) Successful in 2m51s
Native Rust workspace compile / compile (push) Successful in 5m28s
Skia feature / linux (push) Successful in 31m53s
582 lines
24 KiB
Rust
582 lines
24 KiB
Rust
#![allow(clippy::float_cmp)]
|
|
|
|
// Exact BSD-3-Clause fixture provenance at LibreMetaverse
|
|
// 2aa70bb68513b39795da5d13c88f31b86e85a3ba (see LICENSE.md):
|
|
// AssetMaterialOverrideTests.cs 3ec3a8bca08da06c52de1eeea1428b2b83c27660af20580f0333ed67b01bd09b
|
|
// GltfDocumentTests.cs e6e94d5b97a27b8cc4a345f08ab9a9a43b6ce587667edd89d8a4ebbc04eaa646
|
|
// Embedded 44-byte triangle buffer d3478e66e380d8a2b0c9d80f3459f75660efb111e7b801a7d1c1f8f48723d79b
|
|
|
|
use libremetaverse::assets::gltf::{GltfDocument, GltfPrimitive, GltfPrimitiveMode};
|
|
use libremetaverse::assets::{AssetMaterial, GltfAlphaMode};
|
|
use libremetaverse_structured_data::OSDMap;
|
|
use libremetaverse_types::{Color4, Quaternion, UUID, Vector2, Vector3};
|
|
|
|
fn color(r: f32, g: f32, b: f32, a: f32) -> Color4 {
|
|
Color4::new_with_single_single_single_single(r, g, b, a).expect("Color4 constructor")
|
|
}
|
|
|
|
fn vector2(x: f32, y: f32) -> Vector2 {
|
|
Vector2::new_with_single_single(x, y).expect("Vector2 constructor")
|
|
}
|
|
|
|
fn color_values(value: &Color4) -> [f32; 4] {
|
|
[value.r, value.g, value.b, value.a]
|
|
}
|
|
|
|
#[allow(clippy::trivially_copy_pass_by_ref)] // Mirrors the reference-oriented test helper shape.
|
|
fn vector2_values(value: &Vector2) -> [f32; 2] {
|
|
[value.x, value.y]
|
|
}
|
|
|
|
fn vector3_values(value: &Vector3) -> [f32; 3] {
|
|
[value.x, value.y, value.z]
|
|
}
|
|
|
|
fn quaternion_values(value: &Quaternion) -> [f32; 4] {
|
|
[value.x, value.y, value.z, value.w]
|
|
}
|
|
|
|
fn uuid_eq(actual: &UUID, expected: &UUID) {
|
|
assert_eq!(
|
|
actual.get_bytes().expect("actual UUID bytes"),
|
|
expected.get_bytes().expect("expected UUID bytes")
|
|
);
|
|
}
|
|
|
|
fn minimal_gltf_json() -> String {
|
|
r#"{
|
|
"asset": { "version": "2.0", "generator": "Test" },
|
|
"scene": 0,
|
|
"scenes": [{ "name": "Scene", "nodes": [0] }],
|
|
"nodes": [{ "name": "Mesh", "mesh": 0 }],
|
|
"meshes": [{
|
|
"name": "Triangle",
|
|
"primitives": [{
|
|
"attributes": { "POSITION": 0 },
|
|
"indices": 1,
|
|
"material": 0,
|
|
"mode": 4
|
|
}]
|
|
}],
|
|
"materials": [{
|
|
"name": "Mat",
|
|
"pbrMetallicRoughness": {
|
|
"baseColorFactor": [1.0, 0.5, 0.0, 1.0],
|
|
"metallicFactor": 0.0,
|
|
"roughnessFactor": 1.0
|
|
},
|
|
"alphaMode": "OPAQUE",
|
|
"alphaCutoff": 0.5,
|
|
"doubleSided": false
|
|
}],
|
|
"accessors": [
|
|
{
|
|
"bufferView": 0,
|
|
"byteOffset": 0,
|
|
"componentType": 5126,
|
|
"count": 3,
|
|
"type": "VEC3",
|
|
"max": [1.0, 1.0, 0.0],
|
|
"min": [0.0, 0.0, 0.0]
|
|
},
|
|
{
|
|
"bufferView": 1,
|
|
"byteOffset": 0,
|
|
"componentType": 5123,
|
|
"count": 3,
|
|
"type": "SCALAR"
|
|
}
|
|
],
|
|
"bufferViews": [
|
|
{ "buffer": 0, "byteOffset": 0, "byteLength": 36, "target": 34962 },
|
|
{ "buffer": 0, "byteOffset": 36, "byteLength": 6, "target": 34963 }
|
|
],
|
|
"buffers": [{
|
|
"byteLength": 44,
|
|
"uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAABAAIAAAA="
|
|
}]
|
|
}"#
|
|
.into()
|
|
}
|
|
|
|
fn load_document() -> GltfDocument {
|
|
GltfDocument::load_gltf(minimal_gltf_json(), None).expect("GltfDocument LoadGltf")
|
|
}
|
|
|
|
fn first_primitive(document: &GltfDocument) -> GltfPrimitive {
|
|
document.meshes()[0]
|
|
.primitives()
|
|
.into_iter()
|
|
.next()
|
|
.expect("first primitive")
|
|
}
|
|
|
|
fn assert_close(actual: f32, expected: f32, tolerance: f32) {
|
|
assert!((actual - expected).abs() <= tolerance);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetBaseColorFactor_OverrideToDefault_IsNudgedOffDefault::test df553fd4df83e48d4dd74cdd8aa15a737ea3a416bcad802f7110bbfe79928a31 translated
|
|
#[test]
|
|
fn base_color_override_to_default_is_nudged() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
let default = AssetMaterial::default().base_color_factor();
|
|
material
|
|
.set_base_color_factor_with_color4_boolean(default, Some(true))
|
|
.expect("SetBaseColorFactor");
|
|
assert_ne!(
|
|
color_values(&material.base_color_factor()),
|
|
color_values(&AssetMaterial::default().base_color_factor())
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetBaseColorFactor_NotOverride_LeavesExactDefaultUnchanged::test fec94fcfac0f36cc5813ed087a30e04fcc9815bc02072ea3f5dd282b8698a89c translated
|
|
#[test]
|
|
fn base_color_non_override_keeps_default() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
let default = AssetMaterial::default().base_color_factor();
|
|
material
|
|
.set_base_color_factor_with_color4_boolean(default, None)
|
|
.expect("SetBaseColorFactor");
|
|
assert_eq!(
|
|
color_values(&material.base_color_factor()),
|
|
color_values(&AssetMaterial::default().base_color_factor())
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetMetallicFactor_OverrideToOne_ClampsBelowDefault::test 7fcee795160428082f6e579881867c7b6c83f31549077fc28a46d18c75c485c9 translated
|
|
#[test]
|
|
fn metallic_override_to_one_clamps_below_default() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material
|
|
.set_metallic_factor_with_single_boolean(1.0, Some(true))
|
|
.expect("SetMetallicFactor");
|
|
assert!(material.metallic_factor() < 1.0);
|
|
assert_ne!(
|
|
material.metallic_factor(),
|
|
AssetMaterial::default().metallic_factor()
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetAlphaMode_OverrideToDefaultOpaque_SetsOverrideFlag::test 8af09d12a58083657e27e285802bb3a6a1d1c136397cea53865d964006343715 translated
|
|
#[test]
|
|
fn alpha_mode_override_sets_flag() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material
|
|
.set_alpha_mode_with_gltf_alpha_mode_boolean(GltfAlphaMode::Opaque, Some(true))
|
|
.expect("SetAlphaMode");
|
|
assert!(material.override_alpha_mode());
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetTextureId_OverrideToNull_UsesSentinelUuid::test d9ebf410d2a55c3619b99524a571396fb268e5edd41de955cb86e4ec8cc55c78 translated
|
|
#[test]
|
|
fn null_texture_override_uses_sentinel() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material
|
|
.set_texture_id(AssetMaterial::TEXTURE_BASE_COLOR, UUID::zero(), Some(true))
|
|
.expect("SetTextureId");
|
|
uuid_eq(
|
|
&material.texture_ids()[AssetMaterial::TEXTURE_BASE_COLOR as usize],
|
|
&AssetMaterial::gltf_override_null_uuid(),
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ApplyOverride_SentinelTexture_ClearsBaseTexture::test 17fd8cdb12ed5d1d0aa1b0a05dbcc357f75aa350d5079b066c957da459d9f628 translated
|
|
#[test]
|
|
fn sentinel_override_clears_base_texture() {
|
|
let mut base = AssetMaterial::new_with_constructor().expect("base material");
|
|
base.set_texture_id(
|
|
AssetMaterial::TEXTURE_BASE_COLOR,
|
|
UUID::random().expect("UUID Random"),
|
|
None,
|
|
)
|
|
.expect("base texture");
|
|
let mut override_ = AssetMaterial::new_with_constructor().expect("override material");
|
|
override_
|
|
.set_texture_id(AssetMaterial::TEXTURE_BASE_COLOR, UUID::zero(), Some(true))
|
|
.expect("override texture");
|
|
base.apply_override(override_).expect("ApplyOverride");
|
|
uuid_eq(
|
|
&base.texture_ids()[AssetMaterial::TEXTURE_BASE_COLOR as usize],
|
|
&UUID::zero(),
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ApplyOverride_UntouchedTexture_LeavesBaseTextureAlone::test 80ec5e369e3682d92ec6996841b15bda38a3ef6edcd36a2fd9893d8c15459348 translated
|
|
#[test]
|
|
fn untouched_override_keeps_base_texture() {
|
|
let original = UUID::random().expect("UUID Random");
|
|
let original_copy = UUID::new_with_bytes_int32(original.get_bytes().expect("UUID bytes"), 0)
|
|
.expect("UUID copy");
|
|
let mut base = AssetMaterial::new_with_constructor().expect("base material");
|
|
base.set_texture_id(AssetMaterial::TEXTURE_BASE_COLOR, original, None)
|
|
.expect("base texture");
|
|
let override_ = AssetMaterial::new_with_constructor().expect("override material");
|
|
base.apply_override(override_).expect("ApplyOverride");
|
|
uuid_eq(
|
|
&base.texture_ids()[AssetMaterial::TEXTURE_BASE_COLOR as usize],
|
|
&original_copy,
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ApplyOverride_ChangedScalar_ReplacesBaseValue::test 4c305c54c4e451932fbd4a4719957f92f38a7f7d28259559b43cb95fcf9250d1 translated
|
|
#[test]
|
|
fn changed_scalar_override_replaces_base() {
|
|
let mut base = AssetMaterial::new_with_constructor().expect("base material");
|
|
let mut override_ = AssetMaterial::new_with_constructor().expect("override material");
|
|
override_
|
|
.set_roughness_factor_with_single_boolean(0.3, Some(true))
|
|
.expect("SetRoughnessFactor");
|
|
base.apply_override(override_).expect("ApplyOverride");
|
|
assert_eq!(base.roughness_factor(), 0.3);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.SetBaseMaterial_ResetsFieldsButKeepsTransforms::test 39312602e736fd8607a41d9e6b6348bfaf6e659cf3f63100ee15edd20b672306 translated
|
|
#[test]
|
|
fn set_base_material_keeps_texture_transforms() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material.set_name("Foo".into());
|
|
material
|
|
.set_roughness_factor_with_single_boolean(0.2, Some(true))
|
|
.expect("SetRoughnessFactor");
|
|
material
|
|
.set_texture_offset(AssetMaterial::TEXTURE_BASE_COLOR, vector2(0.5, 0.25))
|
|
.expect("SetTextureOffset");
|
|
material.set_base_material().expect("SetBaseMaterial");
|
|
assert_eq!(material.name(), "");
|
|
assert_eq!(
|
|
material.roughness_factor(),
|
|
AssetMaterial::default().roughness_factor()
|
|
);
|
|
assert_eq!(
|
|
vector2_values(
|
|
&material.texture_transforms()[AssetMaterial::TEXTURE_BASE_COLOR as usize].offset,
|
|
),
|
|
vector2_values(&vector2(0.5, 0.25))
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ToOverrideOsd_RoundTrip_PreservesOverriddenFields::test 8d542528a14e3b4dcb74ea8a940a44673aada51f98baf8abcdd59a06f36e3cb0 translated
|
|
#[test]
|
|
fn override_osd_round_trip_preserves_fields() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material
|
|
.set_roughness_factor_with_single_boolean(0.4, Some(true))
|
|
.expect("SetRoughnessFactor");
|
|
material
|
|
.set_metallic_factor_with_single_boolean(0.6, Some(true))
|
|
.expect("SetMetallicFactor");
|
|
let texture = UUID::random().expect("UUID Random");
|
|
let expected =
|
|
UUID::new_with_bytes_int32(texture.get_bytes().expect("UUID bytes"), 0).expect("UUID copy");
|
|
material
|
|
.set_texture_id(AssetMaterial::TEXTURE_EMISSIVE, texture, Some(true))
|
|
.expect("SetTextureId");
|
|
material
|
|
.set_texture_rotation(AssetMaterial::TEXTURE_EMISSIVE, 1.25)
|
|
.expect("SetTextureRotation");
|
|
let osd = material.to_override_osd().expect("ToOverrideOsd");
|
|
let round_trip = AssetMaterial::from_override_osd(osd).expect("FromOverrideOsd");
|
|
assert_eq!(round_trip.roughness_factor(), 0.4);
|
|
assert_eq!(round_trip.metallic_factor(), 0.6);
|
|
uuid_eq(
|
|
&round_trip.texture_ids()[AssetMaterial::TEXTURE_EMISSIVE as usize],
|
|
&expected,
|
|
);
|
|
assert_eq!(
|
|
round_trip.texture_transforms()[AssetMaterial::TEXTURE_EMISSIVE as usize].rotation,
|
|
1.25
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ToOverrideOsd_UntouchedMaterial_ProducesEmptyMap::test c9e29f7ec0e6b28579e0499e3ec89841e01a313a9386ba60257e5e701129b1c2 translated
|
|
#[test]
|
|
fn untouched_material_override_osd_is_empty() {
|
|
let material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
let osd: OSDMap = material.to_override_osd().expect("ToOverrideOsd");
|
|
assert_eq!(osd.count(), 0);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ToOverrideOsd_OverrideToDefaultRoughness_StillEncodesField::test 4ea9920c6709bd29858a8da66313fcee5ebebd646743c5d822dd6c9e477bf3b4 translated
|
|
#[test]
|
|
fn default_roughness_override_is_encoded() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material
|
|
.set_roughness_factor_with_single_boolean(
|
|
AssetMaterial::default().roughness_factor(),
|
|
Some(true),
|
|
)
|
|
.expect("SetRoughnessFactor");
|
|
let osd = material.to_override_osd().expect("ToOverrideOsd");
|
|
assert!(osd.contains_key("rf".into()).expect("ContainsKey"));
|
|
let round_trip = AssetMaterial::from_override_osd(osd).expect("FromOverrideOsd");
|
|
assert_ne!(
|
|
round_trip.roughness_factor(),
|
|
AssetMaterial::default().roughness_factor()
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/AssetMaterialOverrideTests.cs::AssetMaterialOverrideTests.ToJson_RoundTrip_PreservesNameAndColor::test d7ae4270d82671a970fc1b6457292860d24481dd84e9fb919ae60fded5f1914e translated
|
|
#[test]
|
|
fn material_json_round_trip_preserves_name_and_color() {
|
|
let mut material = AssetMaterial::new_with_constructor().expect("AssetMaterial constructor");
|
|
material.set_name("Chrome".into());
|
|
material
|
|
.set_base_color_factor_with_color4_boolean(color(0.1, 0.2, 0.3, 1.0), None)
|
|
.expect("SetBaseColorFactor");
|
|
let json = material.to_json().expect("AssetMaterial ToJson");
|
|
let decoded =
|
|
AssetMaterial::new_with_uuid_bytes(UUID::random().expect("UUID Random"), json.into_bytes())
|
|
.expect("AssetMaterial bytes constructor");
|
|
assert_eq!(decoded.name(), "Chrome");
|
|
assert_eq!(
|
|
color_values(&decoded.base_color_factor()),
|
|
color_values(&material.base_color_factor())
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.LoadGltf_ParsesSceneGraph::test e20583d8de31f793d1dc49d1dfde89e1eb8c00186359e7df4184e862ec9ed649 translated
|
|
#[test]
|
|
fn gltf_parses_scene_graph() {
|
|
let document = load_document();
|
|
assert_eq!(document.version(), "2.0");
|
|
assert_eq!(document.generator().as_deref(), Some("Test"));
|
|
assert_eq!(document.default_scene(), 0);
|
|
assert_eq!(document.scenes().len(), 1);
|
|
assert_eq!(document.scenes()[0].nodes().len(), 1);
|
|
assert_eq!(document.nodes().len(), 1);
|
|
assert_eq!(document.nodes()[0].mesh(), 0);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.LoadGltf_ParsesMeshAndPrimitive::test ef6a76308db1966423c7746f5414f3d0553587efc388bbedb962f38cc122ecaf translated
|
|
#[test]
|
|
fn gltf_parses_mesh_and_primitive() {
|
|
let document = load_document();
|
|
assert_eq!(document.meshes().len(), 1);
|
|
assert_eq!(document.meshes()[0].name().as_deref(), Some("Triangle"));
|
|
assert_eq!(document.meshes()[0].primitives().len(), 1);
|
|
let primitive = first_primitive(&document);
|
|
assert!(primitive.attributes().contains_key("POSITION"));
|
|
assert_eq!(primitive.indices(), 1);
|
|
assert_eq!(primitive.material(), 0);
|
|
assert_eq!(primitive.mode(), GltfPrimitiveMode::Triangles);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.LoadGltf_ParsesMaterial::test 0147b4d7102c5223f247f69fa4cf3daeb0aa6300ad46ef34d6a17163b694c13e translated
|
|
#[test]
|
|
fn gltf_parses_material() {
|
|
let document = load_document();
|
|
assert_eq!(document.materials().len(), 1);
|
|
let material = &document.materials()[0];
|
|
assert_eq!(material.name().as_deref(), Some("Mat"));
|
|
assert_close(material.base_color_factor().r, 1.0, 1e-4);
|
|
assert_close(material.base_color_factor().g, 0.5, 1e-4);
|
|
assert_close(material.metallic_factor(), 0.0, 1e-4);
|
|
assert_close(material.roughness_factor(), 1.0, 1e-4);
|
|
assert_eq!(material.alpha_mode(), GltfAlphaMode::Opaque);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.GetPositions_ReturnsCorrectTriangle::test c3d444122ab73794a011d5a5aafb0c2aa030975393f967e871dc88db200f5e96 translated
|
|
#[test]
|
|
fn gltf_positions_are_correct_triangle() {
|
|
let document = load_document();
|
|
let positions = document
|
|
.get_positions(first_primitive(&document))
|
|
.expect("GetPositions");
|
|
assert_eq!(positions.len(), 3);
|
|
assert_eq!(
|
|
vector3_values(&positions[0]),
|
|
vector3_values(&Vector3::zero())
|
|
);
|
|
assert_close(positions[1].x, 1.0, 1e-5);
|
|
assert_close(positions[1].y, 0.0, 1e-5);
|
|
assert_close(positions[2].x, 0.0, 1e-5);
|
|
assert_close(positions[2].y, 1.0, 1e-5);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.GetIndices_ReturnsCorrectValues::test fa39e87a3dfee7258d9a95907a97cbb107f5add7d6a6f9d9800249bb67e2fc58 translated
|
|
#[test]
|
|
fn gltf_indices_are_correct() {
|
|
let document = load_document();
|
|
let indices = document
|
|
.get_indices(first_primitive(&document))
|
|
.expect("GetIndices");
|
|
assert_eq!(indices, [0, 1, 2]);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.GetPositions_EmptyWhenNoAttribute::test 06c691911ee6933f1884f6540d69afafa1f272acfed827c628580438204d9b4b translated
|
|
#[test]
|
|
fn gltf_positions_empty_without_attribute() {
|
|
let document = load_document();
|
|
let primitive = GltfPrimitive::new().expect("GltfPrimitive constructor");
|
|
assert_eq!(
|
|
document
|
|
.get_positions(primitive)
|
|
.expect("GetPositions")
|
|
.len(),
|
|
0
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.GetNormals_EmptyWhenNoAttribute::test e04480b0b9e23cb561cc55e744ebd85203c759f98ad69febeeb291919f0d91af translated
|
|
#[test]
|
|
fn gltf_normals_empty_without_attribute() {
|
|
let document = load_document();
|
|
assert_eq!(
|
|
document
|
|
.get_normals(first_primitive(&document))
|
|
.expect("GetNormals")
|
|
.len(),
|
|
0
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ToJson_RoundTrip_PreservesSceneGraph::test 41c385b7bde3f8e4f4ad98d4f1f737fc6ccc241c2613526fd745eb35430386b2 translated
|
|
#[test]
|
|
fn gltf_json_round_trip_preserves_scene_graph() {
|
|
let original = load_document();
|
|
let json = original.to_json(None).expect("GltfDocument ToJson");
|
|
let round_trip = GltfDocument::load_gltf(json, None).expect("GltfDocument LoadGltf");
|
|
assert_eq!(round_trip.scenes().len(), original.scenes().len());
|
|
assert_eq!(round_trip.nodes().len(), original.nodes().len());
|
|
assert_eq!(round_trip.meshes().len(), original.meshes().len());
|
|
assert_eq!(round_trip.materials().len(), original.materials().len());
|
|
assert_close(
|
|
round_trip.materials()[0].base_color_factor().r,
|
|
original.materials()[0].base_color_factor().r,
|
|
1e-4,
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ToGlb_RoundTrip_PreservesGeometry::test 1e97fe2d1492ac195f6a4386329c76ad131ab99a41b8e03216b1bab8b48fae36 translated
|
|
#[test]
|
|
fn glb_round_trip_preserves_geometry() {
|
|
let original = load_document();
|
|
let glb = original.to_glb().expect("GltfDocument ToGlb");
|
|
assert_eq!(&glb[..4], &[0x67, 0x6c, 0x54, 0x46]);
|
|
let round_trip = GltfDocument::load(glb, None).expect("GltfDocument Load");
|
|
let positions = round_trip
|
|
.get_positions(first_primitive(&round_trip))
|
|
.expect("GetPositions");
|
|
assert_eq!(positions.len(), 3);
|
|
assert_close(positions[1].x, 1.0, 1e-5);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.Load_AutoDetectsGlbVsJson::test 6d07930be2302e504ef9ece3fef10f47b855d33ae6c8bff152e82df0beb2a474 translated
|
|
#[test]
|
|
fn gltf_load_auto_detects_glb_and_json() {
|
|
let original = load_document();
|
|
let glb = original.to_glb().expect("GltfDocument ToGlb");
|
|
let json = original.to_json(None).expect("GltfDocument ToJson");
|
|
let from_glb = GltfDocument::load(glb, None).expect("load GLB");
|
|
let from_json = GltfDocument::load(json.into_bytes(), None).expect("load JSON");
|
|
assert_eq!(from_glb.meshes().len(), 1);
|
|
assert_eq!(from_json.meshes().len(), 1);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_TrsDefaults::test 0f0fbe116d20276c2aee917b940bded9de277ed0b3e3b659844c5b3532755259 translated
|
|
#[test]
|
|
fn gltf_node_trs_defaults() {
|
|
let document = load_document();
|
|
let node = &document.nodes()[0];
|
|
assert!(node.matrix().is_none());
|
|
assert_eq!(
|
|
vector3_values(&node.translation()),
|
|
vector3_values(&Vector3::zero())
|
|
);
|
|
assert_eq!(
|
|
quaternion_values(&node.rotation()),
|
|
quaternion_values(&Quaternion::identity())
|
|
);
|
|
assert_eq!(
|
|
vector3_values(&node.scale()),
|
|
vector3_values(&Vector3::one())
|
|
);
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_ExplicitMatrix::test 197ba2ee3a66cbb7d927acea13ce9dc84e62af8a500d939957749039118755c8 translated
|
|
#[test]
|
|
fn gltf_node_explicit_matrix() {
|
|
let document = GltfDocument::load_gltf(
|
|
r#"{
|
|
"asset": { "version": "2.0" },
|
|
"nodes": [{
|
|
"matrix": [1,0,0,0, 0,1,0,0, 0,0,1,0, 5,6,7,1]
|
|
}]
|
|
}"#
|
|
.into(),
|
|
None,
|
|
)
|
|
.expect("GltfDocument LoadGltf");
|
|
let matrix = document.nodes()[0]
|
|
.matrix()
|
|
.flatten()
|
|
.expect("explicit matrix");
|
|
assert_close(matrix.m14, 5.0, 1e-5);
|
|
assert_close(matrix.m24, 6.0, 1e-5);
|
|
assert_close(matrix.m34, 7.0, 1e-5);
|
|
}
|
|
|
|
#[test]
|
|
fn gltf_rejects_buffer_view_outside_declared_buffer() {
|
|
let json = r#"{
|
|
"asset":{"version":"2.0"},
|
|
"buffers":[{"byteLength":4,"uri":"data:application/octet-stream;base64,AAAAAA=="}],
|
|
"bufferViews":[{"buffer":0,"byteOffset":3,"byteLength":4}]
|
|
}"#;
|
|
assert!(GltfDocument::load_gltf(json.into(), None).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn gltf_rejects_cyclic_node_graphs() {
|
|
let json = r#"{
|
|
"asset":{"version":"2.0"},
|
|
"nodes":[{"children":[1]},{"children":[0]}],
|
|
"scenes":[{"nodes":[0]}],
|
|
"scene":0
|
|
}"#;
|
|
assert!(GltfDocument::load_gltf(json.into(), None).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn gltf_surface_skin_and_animation_round_trip() {
|
|
let json = r#"{
|
|
"asset":{"version":"2.0"},
|
|
"accessors":[
|
|
{"componentType":5126,"count":0,"type":"SCALAR"},
|
|
{"componentType":5126,"count":0,"type":"VEC3"}
|
|
],
|
|
"images":[{"uri":"data:image/png;base64,iVBORw0KGgo=","mimeType":"image/png","name":"image"}],
|
|
"samplers":[{"magFilter":9729,"minFilter":9987,"wrapS":10497,"wrapT":33071,"name":"sampler"}],
|
|
"textures":[{"sampler":0,"source":0,"name":"texture"}],
|
|
"materials":[{
|
|
"name":"surface",
|
|
"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicRoughnessTexture":{"index":0}},
|
|
"normalTexture":{"index":0,"scale":0.5},
|
|
"occlusionTexture":{"index":0,"strength":0.75},
|
|
"emissiveTexture":{"index":0},
|
|
"emissiveFactor":[0.1,0.2,0.3]
|
|
}],
|
|
"nodes":[{"skin":0}],
|
|
"skins":[{"joints":[0],"skeleton":0,"name":"skin"}],
|
|
"animations":[{
|
|
"name":"move",
|
|
"samplers":[{"input":0,"output":1,"interpolation":"LINEAR"}],
|
|
"channels":[{"sampler":0,"target":{"node":0,"path":"translation"}}]
|
|
}]
|
|
}"#;
|
|
let document = GltfDocument::load_gltf(json.into(), None).expect("load complete surface");
|
|
let serialized = document.to_json(None).expect("serialize complete surface");
|
|
let round_trip = GltfDocument::load_gltf(serialized, None).expect("reload complete surface");
|
|
assert_eq!(round_trip.images().len(), 1);
|
|
assert_eq!(round_trip.samplers().len(), 1);
|
|
assert_eq!(round_trip.textures().len(), 1);
|
|
assert_eq!(round_trip.skins()[0].joints(), [0]);
|
|
assert_eq!(round_trip.animations()[0].channels().len(), 1);
|
|
let material = &round_trip.materials()[0];
|
|
assert!(material.base_color_texture().is_some());
|
|
assert!(material.metallic_roughness_texture().is_some());
|
|
assert!(material.normal_texture().is_some());
|
|
assert!(material.occlusion_texture().is_some());
|
|
assert!(material.emissive_texture().is_some());
|
|
}
|