use std::{borrow::Cow, collections::BTreeMap};
use super::Result;
use awsm_renderer_core::pipeline::primitive::FrontFace;
use crate::{
gltf::{
buffers::{mesh::get_vec3_from_buffer, MeshBufferAttributeIndexInfoWithOffset},
error::AwsmGltfError,
},
meshes::buffer_info::{MeshBufferVertexAttributeInfo, MeshBufferVisibilityVertexAttributeInfo},
};
pub(super) fn create_transparency_vertices(
attribute_data: &BTreeMap<MeshBufferVertexAttributeInfo, Cow<'_, [u8]>>,
_index: &MeshBufferAttributeIndexInfoWithOffset,
_index_bytes: &[u8],
_triangle_count: usize,
_front_face: FrontFace,
transparency_vertex_bytes: &mut Vec<u8>,
) -> Result<()> {
let positions = attribute_data
.iter()
.find_map(|(attr_info, data)| match attr_info {
MeshBufferVertexAttributeInfo::Visibility(
MeshBufferVisibilityVertexAttributeInfo::Positions { .. },
) => Some(&data[..]),
_ => None,
})
.ok_or_else(|| AwsmGltfError::Positions("missing positions".to_string()))?;
let normals = attribute_data
.iter()
.find_map(|(attr_info, data)| match attr_info {
MeshBufferVertexAttributeInfo::Visibility(
MeshBufferVisibilityVertexAttributeInfo::Normals { .. },
) => Some(&data[..]),
_ => None,
})
.ok_or_else(|| AwsmGltfError::AttributeData("missing normals".to_string()))?;
let tangents = attribute_data
.iter()
.find_map(|(attr_info, data)| match attr_info {
MeshBufferVertexAttributeInfo::Visibility(
MeshBufferVisibilityVertexAttributeInfo::Tangents { .. },
) => Some(&data[..]),
_ => None,
});
if positions.len() % 12 != 0 {
return Err(AwsmGltfError::Positions(format!(
"Position buffer length ({}) is not a multiple of 12 (3 * f32).",
positions.len()
)));
}
if normals.len() % 12 != 0 {
return Err(AwsmGltfError::AttributeData(format!(
"Normal buffer length ({}) is not a multiple of 12 (3 * f32).",
normals.len()
)));
}
if let Some(tangents) = tangents {
if tangents.len() % 16 != 0 {
return Err(AwsmGltfError::AttributeData(format!(
"Tangent buffer length ({}) is not a multiple of 16 (4 * f32).",
tangents.len()
)));
}
}
let vertex_count = positions.len() / 12;
for vertex_index in 0..vertex_count {
let position = get_vec3_from_buffer(positions, vertex_index, "position")?;
let normal = get_vec3_from_buffer(normals, vertex_index, "normal")?;
let tangent = if let Some(tangents) = tangents {
[
f32::from_le_bytes([
tangents[vertex_index * 16],
tangents[vertex_index * 16 + 1],
tangents[vertex_index * 16 + 2],
tangents[vertex_index * 16 + 3],
]),
f32::from_le_bytes([
tangents[vertex_index * 16 + 4],
tangents[vertex_index * 16 + 5],
tangents[vertex_index * 16 + 6],
tangents[vertex_index * 16 + 7],
]),
f32::from_le_bytes([
tangents[vertex_index * 16 + 8],
tangents[vertex_index * 16 + 9],
tangents[vertex_index * 16 + 10],
tangents[vertex_index * 16 + 11],
]),
f32::from_le_bytes([
tangents[vertex_index * 16 + 12],
tangents[vertex_index * 16 + 13],
tangents[vertex_index * 16 + 14],
tangents[vertex_index * 16 + 15],
]),
]
} else {
[0.0, 0.0, 0.0, 1.0] };
transparency_vertex_bytes.extend_from_slice(&position[0].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&position[1].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&position[2].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&normal[0].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&normal[1].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&normal[2].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&tangent[0].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&tangent[1].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&tangent[2].to_le_bytes());
transparency_vertex_bytes.extend_from_slice(&tangent[3].to_le_bytes());
}
Ok(())
}