use draco_core::decoder_buffer::DecoderBuffer;
use draco_core::draco_types::DataType;
use draco_core::encoder_buffer::EncoderBuffer;
use draco_core::encoder_options::EncoderOptions;
use draco_core::geometry_attribute::{GeometryAttributeType, PointAttribute};
use draco_core::geometry_indices::{FaceIndex, PointIndex};
use draco_core::mesh::Mesh;
use draco_core::mesh_decoder::MeshDecoder;
use draco_core::mesh_encoder::MeshEncoder;
fn decoded_bytes(mesh: &Mesh) -> Vec<u8> {
let mut out = Vec::new();
out.extend((mesh.num_points() as u64).to_le_bytes());
out.extend((mesh.num_faces() as u64).to_le_bytes());
for f in 0..mesh.num_faces() {
for corner in mesh.face(FaceIndex(f as u32)) {
out.extend(corner.0.to_le_bytes());
}
}
out.extend((mesh.num_attributes() as u32).to_le_bytes());
for id in 0..mesh.num_attributes() {
let att = mesh.attribute(id);
out.push(att.attribute_type() as u8);
out.push(att.num_components());
out.push(att.data_type() as u8);
let stride = att.byte_stride() as usize;
let mut value = vec![0u8; stride];
for p in 0..mesh.num_points() {
let index = att.mapped_index(PointIndex(p as u32));
att.buffer().read(index.0 as usize * stride, &mut value);
out.extend_from_slice(&value);
}
}
out
}
#[test]
fn a_reused_decoder_and_mesh_decode_what_fresh_ones_do() {
let mut edgebreaker = EncoderOptions::new();
edgebreaker.set_global_int("encoding_method", 1);
edgebreaker.set_attribute_int(0, "quantization_bits", 11);
edgebreaker.set_attribute_int(1, "quantization_bits", 10);
let mut sequential = EncoderOptions::new();
sequential.set_global_int("encoding_method", 0);
sequential.set_attribute_int(0, "quantization_bits", 8);
let first = encode(uv_quad(), &edgebreaker);
let second = encode(triangle(), &sequential);
let mut from_fresh = Mesh::new();
MeshDecoder::new()
.decode(&mut DecoderBuffer::new(&second), &mut from_fresh)
.expect("fresh decode");
let mut reused = Mesh::new();
let mut decoder = MeshDecoder::new();
decoder
.decode(&mut DecoderBuffer::new(&first), &mut reused)
.expect("first decode");
decoder
.decode(&mut DecoderBuffer::new(&second), &mut reused)
.expect("second decode into the same mesh");
assert_eq!(
decoded_bytes(&from_fresh),
decoded_bytes(&reused),
"a reused decoder and mesh produced a different mesh than fresh ones"
);
}
fn encode(mesh: Mesh, options: &EncoderOptions) -> Vec<u8> {
let mut encoder = MeshEncoder::new();
encoder.set_mesh(mesh);
let mut buffer = EncoderBuffer::new();
encoder.encode(options, &mut buffer).expect("encode");
buffer.data().to_vec()
}
fn positions(mesh: &mut Mesh, values: &[[f32; 3]]) {
let mut att = PointAttribute::new();
att.init(
GeometryAttributeType::Position,
3,
DataType::Float32,
false,
values.len(),
);
for (i, value) in values.iter().enumerate() {
let bytes: Vec<u8> = value.iter().flat_map(|v| v.to_le_bytes()).collect();
att.buffer_mut().write(i * 12, &bytes);
}
mesh.add_attribute(att);
}
fn uv_quad() -> Mesh {
let mut mesh = Mesh::new();
positions(
&mut mesh,
&[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
],
);
let mut uv = PointAttribute::new();
uv.init(
GeometryAttributeType::TexCoord,
2,
DataType::Float32,
false,
4,
);
for (i, value) in [[0.0f32, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]
.iter()
.enumerate()
{
let bytes: Vec<u8> = value.iter().flat_map(|v| v.to_le_bytes()).collect();
uv.buffer_mut().write(i * 8, &bytes);
}
mesh.add_attribute(uv);
mesh.set_num_faces(2);
mesh.set_face(FaceIndex(0), [PointIndex(0), PointIndex(1), PointIndex(2)]);
mesh.set_face(FaceIndex(1), [PointIndex(0), PointIndex(2), PointIndex(3)]);
mesh
}
fn triangle() -> Mesh {
let mut mesh = Mesh::new();
positions(
&mut mesh,
&[[0.0, 0.0, 0.0], [2.0, 0.0, 0.0], [0.0, 3.0, 1.0]],
);
mesh.set_num_faces(1);
mesh.set_face(FaceIndex(0), [PointIndex(0), PointIndex(1), PointIndex(2)]);
mesh
}
#[test]
fn test_mesh_encode_decode() {
let mut mesh = Mesh::new();
let mut pos_att = PointAttribute::new();
let num_points = 4;
pos_att.init(
GeometryAttributeType::Position,
3,
DataType::Float32,
false,
num_points,
);
let positions: [f32; 12] = [
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, ];
let buffer = pos_att.buffer_mut();
for i in 0..num_points {
let bytes = [
positions[i * 3].to_le_bytes(),
positions[i * 3 + 1].to_le_bytes(),
positions[i * 3 + 2].to_le_bytes(),
]
.concat();
buffer.write(i * 12, &bytes);
}
mesh.add_attribute(pos_att);
mesh.set_num_faces(2);
mesh.set_face(FaceIndex(0), [PointIndex(0), PointIndex(1), PointIndex(2)]);
mesh.set_face(FaceIndex(1), [PointIndex(0), PointIndex(2), PointIndex(3)]);
let mut encoder = MeshEncoder::new();
encoder.set_mesh(mesh);
let mut options = EncoderOptions::new();
options.set_attribute_int(0, "quantization_bits", 10);
let mut enc_buffer = EncoderBuffer::new();
let status = encoder.encode(&options, &mut enc_buffer);
assert!(status.is_ok(), "Encoding failed: {:?}", status.err());
let mut dec_buffer = DecoderBuffer::new(enc_buffer.data());
let mut decoded_mesh = Mesh::new();
let mut decoder = MeshDecoder::new();
let status = decoder.decode(&mut dec_buffer, &mut decoded_mesh);
assert!(status.is_ok(), "Decoding failed: {:?}", status.err());
assert_eq!(decoded_mesh.num_faces(), 2);
assert_eq!(decoded_mesh.num_points(), 4);
let decoded_att = decoded_mesh.attribute(0);
assert_eq!(
decoded_att.attribute_type(),
GeometryAttributeType::Position
);
let read_pos = |idx: usize| -> [f32; 3] {
let decoded_buffer = decoded_att.buffer();
let mut bytes = [0u8; 12];
decoded_buffer.read(idx * 12, &mut bytes);
[
f32::from_le_bytes(bytes[0..4].try_into().unwrap()),
f32::from_le_bytes(bytes[4..8].try_into().unwrap()),
f32::from_le_bytes(bytes[8..12].try_into().unwrap()),
]
};
let decoded_positions: Vec<[f32; 3]> = (0..num_points).map(read_pos).collect();
let original_positions: Vec<[f32; 3]> = (0..num_points)
.map(|i| [positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]])
.collect();
for orig in &original_positions {
let found = decoded_positions.iter().any(|dec| {
(dec[0] - orig[0]).abs() < 0.01
&& (dec[1] - orig[1]).abs() < 0.01
&& (dec[2] - orig[2]).abs() < 0.01
});
assert!(
found,
"Original position {:?} not found in decoded mesh",
orig
);
}
}