diff --git a/Source/Core/VideoCommon/Assets/MeshAsset.cpp b/Source/Core/VideoCommon/Assets/MeshAsset.cpp index bde8c8aab6..72c681fa33 100644 --- a/Source/Core/VideoCommon/Assets/MeshAsset.cpp +++ b/Source/Core/VideoCommon/Assets/MeshAsset.cpp @@ -33,12 +33,11 @@ Common::Matrix44 BuildMatrixFromNode(const tinygltf::Node& node) Common::Matrix44 matrix = Common::Matrix44::Identity(); // Check individual components - - if (!node.scale.empty()) + if (!node.translation.empty()) { - matrix *= Common::Matrix44::FromMatrix33(Common::Matrix33::Scale( - Common::Vec3{static_cast(node.scale[0]), static_cast(node.scale[1]), - static_cast(node.scale[2])})); + matrix *= Common::Matrix44::Translate(Common::Vec3{static_cast(node.translation[0]), + static_cast(node.translation[1]), + static_cast(node.translation[2])}); } if (!node.rotation.empty()) @@ -48,11 +47,11 @@ Common::Matrix44 BuildMatrixFromNode(const tinygltf::Node& node) static_cast(node.rotation[1]), static_cast(node.rotation[2]))); } - if (!node.translation.empty()) + if (!node.scale.empty()) { - matrix *= Common::Matrix44::Translate(Common::Vec3{static_cast(node.translation[0]), - static_cast(node.translation[1]), - static_cast(node.translation[2])}); + matrix *= Common::Matrix44::FromMatrix33(Common::Matrix33::Scale( + Common::Vec3{static_cast(node.scale[0]), static_cast(node.scale[1]), + static_cast(node.scale[2])})); } return matrix; @@ -291,12 +290,12 @@ bool ReadGLTFMesh(std::string_view mesh_file, const tinygltf::Model& model, chunk.num_vertices = static_cast(pos_accessor.count); // TODO C++23: use make_unique_overwrite chunk.vertex_data = std::unique_ptr(new u8[chunk.num_vertices * chunk.vertex_stride]); + chunk.vertex_declaration.position.offset = static_cast(outbound_offset); if (!CopyBufferDataFromPrimitive(model, position_it->second, &outbound_offset, &chunk)) return false; chunk.components_available = 0; chunk.vertex_declaration.position.enable = true; chunk.vertex_declaration.position.components = 3; - chunk.vertex_declaration.position.offset = 0; if (!GLTFComponentTypeToAttributeFormat(pos_accessor.componentType, &chunk.vertex_declaration.position)) { @@ -454,18 +453,27 @@ bool ReadGLTFMaterials(std::string_view mesh_file, const tinygltf::Model& model, bool ReadGLTF(std::string_view mesh_file, const tinygltf::Model& model, MeshData* data) { - int scene_index = model.defaultScene; - if (scene_index == -1) - scene_index = 0; - - const auto& scene = model.scenes[scene_index]; - const auto scene_node_indices = scene.nodes; - for (std::size_t i = 0; i < scene_node_indices.size(); i++) + const int scene_index = model.defaultScene; + if (scene_index != -1) { - const tinygltf::Node& node = model.nodes[scene_node_indices[i]]; - const auto mat = BuildMatrixFromNode(node); - if (!ReadGLTFNodes(mesh_file, model, node, mat, data)) - return false; + const auto& scene = model.scenes[scene_index]; + const auto scene_node_indices = scene.nodes; + for (std::size_t i = 0; i < scene_node_indices.size(); i++) + { + const tinygltf::Node& node = model.nodes[scene_node_indices[i]]; + const auto mat = BuildMatrixFromNode(node); + if (!ReadGLTFNodes(mesh_file, model, node, mat, data)) + return false; + } + } + else + { + for (const auto& node : model.nodes) + { + const auto mat = BuildMatrixFromNode(node); + if (!ReadGLTFNodes(mesh_file, model, node, mat, data)) + return false; + } } return ReadGLTFMaterials(mesh_file, model, data); @@ -514,6 +522,57 @@ void MeshData::ToJson(picojson::object& obj, const MeshData& data) bool MeshData::FromDolphinMesh(std::span raw_data, MeshData* data) { + const auto read_chunk = [](std::span raw_data, MeshDataChunk* mesh_data_chunk, + std::size_t* offset) { + auto& chunk = *mesh_data_chunk; + std::memcpy(&chunk.num_vertices, raw_data.data() + *offset, sizeof(u32)); + *offset += sizeof(u32); + + std::memcpy(&chunk.vertex_stride, raw_data.data() + *offset, sizeof(u32)); + *offset += sizeof(u32); + + // TODO C++23: use make_unique_overwrite + chunk.vertex_data = std::unique_ptr(new u8[chunk.num_vertices * chunk.vertex_stride]); + std::memcpy(chunk.vertex_data.get(), raw_data.data() + *offset, + chunk.num_vertices * chunk.vertex_stride); + *offset += chunk.num_vertices * chunk.vertex_stride; + + std::memcpy(&chunk.num_indices, raw_data.data() + *offset, sizeof(u32)); + *offset += sizeof(u32); + + // TODO C++23: use make_unique_overwrite + chunk.indices = std::unique_ptr(new u16[chunk.num_indices]); + std::memcpy(chunk.indices.get(), raw_data.data() + *offset, chunk.num_indices * sizeof(u16)); + *offset += chunk.num_indices * sizeof(u16); + + std::memcpy(&chunk.vertex_declaration, raw_data.data() + *offset, + sizeof(PortableVertexDeclaration)); + *offset += sizeof(PortableVertexDeclaration); + + std::memcpy(&chunk.primitive_type, raw_data.data() + *offset, sizeof(PrimitiveType)); + *offset += sizeof(PrimitiveType); + + std::memcpy(&chunk.components_available, raw_data.data() + *offset, sizeof(u32)); + *offset += sizeof(u32); + + std::memcpy(&chunk.minimum_position, raw_data.data() + *offset, sizeof(Common::Vec3)); + *offset += sizeof(Common::Vec3); + + std::memcpy(&chunk.maximum_position, raw_data.data() + *offset, sizeof(Common::Vec3)); + *offset += sizeof(Common::Vec3); + + std::memcpy(&chunk.transform.data[0], raw_data.data() + *offset, + chunk.transform.data.size() * sizeof(float)); + *offset += chunk.transform.data.size() * sizeof(float); + + std::size_t material_name_size = 0; + std::memcpy(&material_name_size, raw_data.data() + *offset, sizeof(std::size_t)); + *offset += sizeof(std::size_t); + + chunk.material_name.assign(raw_data.data() + *offset, + raw_data.data() + *offset + material_name_size); + *offset += material_name_size * sizeof(char); + }; std::size_t offset = 0; std::size_t chunk_size = 0; @@ -524,56 +583,32 @@ bool MeshData::FromDolphinMesh(std::span raw_data, MeshData* data) for (std::size_t i = 0; i < chunk_size; i++) { MeshDataChunk chunk; + read_chunk(raw_data, &chunk, &offset); + data->m_mesh_chunks.push_back(std::move(chunk)); + } - std::memcpy(&chunk.num_vertices, raw_data.data() + offset, sizeof(u32)); - offset += sizeof(u32); + std::size_t gpu_skinning_size = 0; + std::memcpy(&gpu_skinning_size, raw_data.data() + offset, sizeof(std::size_t)); + offset += sizeof(std::size_t); + for (std::size_t i = 0; i < gpu_skinning_size; i++) + { + GraphicsModSystem::DrawCallID draw_call_id; + std::memcpy(&draw_call_id, raw_data.data() + offset, sizeof(GraphicsModSystem::DrawCallID)); + offset += sizeof(GraphicsModSystem::DrawCallID); - std::memcpy(&chunk.vertex_stride, raw_data.data() + offset, sizeof(u32)); - offset += sizeof(u32); - - // TODO C++23: use make_unique_overwrite - chunk.vertex_data = std::unique_ptr(new u8[chunk.num_vertices * chunk.vertex_stride]); - std::memcpy(chunk.vertex_data.get(), raw_data.data() + offset, - chunk.num_vertices * chunk.vertex_stride); - offset += chunk.num_vertices * chunk.vertex_stride; - - std::memcpy(&chunk.num_indices, raw_data.data() + offset, sizeof(u32)); - offset += sizeof(u32); - - // TODO C++23: use make_unique_overwrite - chunk.indices = std::unique_ptr(new u16[chunk.num_indices]); - std::memcpy(chunk.indices.get(), raw_data.data() + offset, chunk.num_indices * sizeof(u16)); - offset += chunk.num_indices * sizeof(u16); - - std::memcpy(&chunk.vertex_declaration, raw_data.data() + offset, - sizeof(PortableVertexDeclaration)); - offset += sizeof(PortableVertexDeclaration); - - std::memcpy(&chunk.primitive_type, raw_data.data() + offset, sizeof(PrimitiveType)); - offset += sizeof(PrimitiveType); - - std::memcpy(&chunk.components_available, raw_data.data() + offset, sizeof(u32)); - offset += sizeof(u32); - - std::memcpy(&chunk.minimum_position, raw_data.data() + offset, sizeof(Common::Vec3)); - offset += sizeof(Common::Vec3); - - std::memcpy(&chunk.maximum_position, raw_data.data() + offset, sizeof(Common::Vec3)); - offset += sizeof(Common::Vec3); - - std::memcpy(&chunk.transform.data[0], raw_data.data() + offset, - chunk.transform.data.size() * sizeof(float)); - offset += chunk.transform.data.size() * sizeof(float); - - std::size_t material_name_size = 0; - std::memcpy(&material_name_size, raw_data.data() + offset, sizeof(std::size_t)); + std::size_t gpu_skinning_chunk_size = 0; + std::memcpy(&gpu_skinning_chunk_size, raw_data.data() + offset, sizeof(std::size_t)); offset += sizeof(std::size_t); - chunk.material_name.assign(raw_data.data() + offset, - raw_data.data() + offset + material_name_size); - offset += material_name_size * sizeof(char); + std::vector gpu_skinning_chunks; + for (std::size_t chunk_index = 0; chunk_index < gpu_skinning_chunk_size; chunk_index++) + { + MeshDataChunk chunk; + read_chunk(raw_data, &chunk, &offset); + gpu_skinning_chunks.push_back(std::move(chunk)); + } - data->m_mesh_chunks.push_back(std::move(chunk)); + data->m_gpu_skinning_chunks.try_emplace(draw_call_id, std::move(gpu_skinning_chunks)); } return true; @@ -581,10 +616,7 @@ bool MeshData::FromDolphinMesh(std::span raw_data, MeshData* data) bool MeshData::ToDolphinMesh(File::IOFile* file_data, const MeshData& data) { - const std::size_t chunk_size = data.m_mesh_chunks.size(); - file_data->WriteBytes(&chunk_size, sizeof(std::size_t)); - for (const auto& chunk : data.m_mesh_chunks) - { + const auto write_chunk = [](File::IOFile* file_data, const VideoCommon::MeshDataChunk& chunk) { if (!file_data->WriteBytes(&chunk.num_vertices, sizeof(u32))) return false; if (!file_data->WriteBytes(&chunk.vertex_stride, sizeof(u32))) @@ -616,7 +648,37 @@ bool MeshData::ToDolphinMesh(File::IOFile* file_data, const MeshData& data) return false; if (!file_data->WriteBytes(&chunk.material_name[0], chunk.material_name.size() * sizeof(char))) return false; + + return true; + }; + + const std::size_t chunk_size = data.m_mesh_chunks.size(); + file_data->WriteBytes(&chunk_size, sizeof(std::size_t)); + for (const auto& chunk : data.m_mesh_chunks) + { + if (!write_chunk(file_data, chunk)) + return false; } + + const std::size_t gpu_skinning_map_size = data.m_gpu_skinning_chunks.size(); + if (!file_data->WriteBytes(&gpu_skinning_map_size, sizeof(std::size_t))) + return false; + for (const auto& [draw_call, gpu_skinning_chunks] : data.m_gpu_skinning_chunks) + { + if (!file_data->WriteBytes(&draw_call, sizeof(GraphicsModSystem::DrawCallID))) + return false; + + const std::size_t gpu_skinning_chunk_size = gpu_skinning_chunks.size(); + if (!file_data->WriteBytes(&gpu_skinning_chunk_size, sizeof(std::size_t))) + return false; + + for (const auto& gpu_skinning_chunk : gpu_skinning_chunks) + { + if (!write_chunk(file_data, gpu_skinning_chunk)) + return false; + } + } + return true; } diff --git a/Source/Core/VideoCommon/Assets/MeshAsset.h b/Source/Core/VideoCommon/Assets/MeshAsset.h index a678b14cee..32bcbdecc6 100644 --- a/Source/Core/VideoCommon/Assets/MeshAsset.h +++ b/Source/Core/VideoCommon/Assets/MeshAsset.h @@ -15,6 +15,7 @@ #include "Common/Matrix.h" #include "VideoCommon/Assets/CustomAsset.h" +#include "VideoCommon/GraphicsModSystem/Types.h" #include "VideoCommon/NativeVertexFormat.h" #include "VideoCommon/RenderState.h" @@ -54,6 +55,7 @@ struct MeshData static bool FromGLTF(std::string_view gltf_file, MeshData* data); std::vector m_mesh_chunks; + std::map> m_gpu_skinning_chunks; std::map> m_mesh_material_to_material_asset_id; };