Complete imaging and meshing integration gate (#44)
Some checks failed
Imaging and meshing gate / native (macos-latest) (push) Has been cancelled
Imaging and meshing gate / native (ubuntu-latest) (push) Has been cancelled
Imaging and meshing gate / native (windows-latest) (push) Has been cancelled
JPEG 2000 feature / linux (push) Has been cancelled
JPEG 2000 feature / macos (push) Has been cancelled
JPEG 2000 feature / windows (push) Has been cancelled
Skia feature / linux (push) Has been cancelled
Skia feature / macos (push) Has been cancelled
Skia feature / windows (push) Has been cancelled
Some checks failed
Imaging and meshing gate / native (macos-latest) (push) Has been cancelled
Imaging and meshing gate / native (ubuntu-latest) (push) Has been cancelled
Imaging and meshing gate / native (windows-latest) (push) Has been cancelled
JPEG 2000 feature / linux (push) Has been cancelled
JPEG 2000 feature / macos (push) Has been cancelled
JPEG 2000 feature / windows (push) Has been cancelled
Skia feature / linux (push) Has been cancelled
Skia feature / macos (push) Has been cancelled
Skia feature / windows (push) Has been cancelled
This commit is contained in:
111
crates/libremetaverse-prim-mesher/tests/rendering_contract.rs
Normal file
111
crates/libremetaverse-prim-mesher/tests/rendering_contract.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
//! Integration contracts for the data consumed by the future rendering pipeline.
|
||||
|
||||
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
|
||||
use libremetaverse_prim_mesher::{
|
||||
PathType, PrimMesh, SculptMesh, SculptMeshSculptType, ViewerPolygon, ViewerVertex,
|
||||
};
|
||||
|
||||
fn assert_rendering_vertices(vertices: &[ViewerVertex], polygons: &[ViewerPolygon]) {
|
||||
assert!(vertices.len() <= usize::from(u16::MAX) + 1);
|
||||
for vertex in vertices {
|
||||
assert!(vertex.v.x.is_finite() && vertex.v.y.is_finite() && vertex.v.z.is_finite());
|
||||
assert!(vertex.n.x.is_finite() && vertex.n.y.is_finite() && vertex.n.z.is_finite());
|
||||
assert!(vertex.uv.u.is_finite() && vertex.uv.v.is_finite());
|
||||
}
|
||||
for polygon in polygons {
|
||||
for index in [polygon.v1, polygon.v2, polygon.v3] {
|
||||
let index = usize::try_from(index).expect("non-negative viewer index");
|
||||
assert!(index < vertices.len());
|
||||
u16::try_from(index).expect("MeshFoundry-facing index fits u16");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prim_mesh_viewer_groups_are_rendering_ready() {
|
||||
let mut mesh = PrimMesh::new(24, 0.05, 0.95, 0.25, 12).expect("checked profile");
|
||||
mesh.viewer_mode = true;
|
||||
mesh.calc_vertex_normals = true;
|
||||
mesh.path_cut_begin = 0.03;
|
||||
mesh.path_cut_end = 0.96;
|
||||
mesh.twist_begin = -30;
|
||||
mesh.twist_end = 120;
|
||||
mesh.taper_x = 0.1;
|
||||
mesh.skew = 0.15;
|
||||
mesh.revolutions = 1.25;
|
||||
mesh.steps_per_revolution = 48;
|
||||
mesh.extrude(PathType::Circular)
|
||||
.expect("checked viewer extrusion");
|
||||
|
||||
let indexer = mesh
|
||||
.get_vertex_indexer()
|
||||
.expect("checked viewer indexing")
|
||||
.expect("viewer mode produces an indexer");
|
||||
assert_eq!(indexer.num_prim_faces, mesh.num_prim_faces);
|
||||
assert_eq!(indexer.viewer_vertices.len(), indexer.viewer_polygons.len());
|
||||
for (vertices, polygons) in indexer
|
||||
.viewer_vertices
|
||||
.iter()
|
||||
.zip(indexer.viewer_polygons.iter())
|
||||
{
|
||||
assert_rendering_vertices(
|
||||
vertices,
|
||||
polygons
|
||||
.as_deref()
|
||||
.expect("allocated prim-face polygon group"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sculpt_lods_and_topologies_keep_rendering_indices_and_attributes_aligned() {
|
||||
let mut image = ManagedImage::new(128, 128, ManagedImageImageChannels::COLOR)
|
||||
.expect("bounded sculpt fixture");
|
||||
for index in 0..image.red.len() {
|
||||
image.red[index] = u8::try_from(index & 0xff).expect("masked sample");
|
||||
image.green[index] = u8::try_from((index / 128) & 0xff).expect("masked sample");
|
||||
image.blue[index] = u8::try_from((index * 17) & 0xff).expect("masked sample");
|
||||
}
|
||||
|
||||
for lod in [8, 16, 32] {
|
||||
for topology in [
|
||||
SculptMeshSculptType::Plane,
|
||||
SculptMeshSculptType::Sphere,
|
||||
SculptMeshSculptType::Torus,
|
||||
SculptMeshSculptType::Cylinder,
|
||||
] {
|
||||
let mesh =
|
||||
SculptMesh::new_with_managed_image_sculpt_type_int32_boolean_boolean_boolean(
|
||||
image.clone().expect("independent image fixture"),
|
||||
topology,
|
||||
lod,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.expect("checked sculpt mesh");
|
||||
assert_eq!(mesh.coords.len(), mesh.normals.len());
|
||||
assert_eq!(mesh.coords.len(), mesh.uvs.len());
|
||||
assert_eq!(mesh.faces.len(), mesh.viewer_faces.len());
|
||||
assert!(mesh.coords.len() <= usize::from(u16::MAX) + 1);
|
||||
for face in &mesh.faces {
|
||||
for index in [face.v1, face.v2, face.v3] {
|
||||
let index = usize::try_from(index).expect("non-negative sculpt index");
|
||||
assert!(index < mesh.coords.len());
|
||||
u16::try_from(index).expect("MeshFoundry-facing sculpt index fits u16");
|
||||
}
|
||||
}
|
||||
for viewer in &mesh.viewer_faces {
|
||||
for coord in [viewer.v1, viewer.v2, viewer.v3] {
|
||||
assert!(coord.x.is_finite() && coord.y.is_finite() && coord.z.is_finite());
|
||||
}
|
||||
for normal in [viewer.n1, viewer.n2, viewer.n3] {
|
||||
assert!(normal.x.is_finite() && normal.y.is_finite() && normal.z.is_finite());
|
||||
}
|
||||
for uv in [viewer.uv1, viewer.uv2, viewer.uv3] {
|
||||
assert!(uv.u.is_finite() && uv.v.is_finite());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user