From 9cd723e282252a05fb99c609550f88b3057d6242 Mon Sep 17 00:00:00 2001 From: "J.G.Adams" <82924084+JG-Adams@users.noreply.github.com> Date: Fri, 26 Aug 2022 19:12:11 -0400 Subject: [PATCH 1/8] Wrong object is created here! If I'm not mistaken. Because this is originally push_back(aniMeshVertex) instead of push_back(v). And the fact that aniMeshVertex is just getting created and destroyed for nothing. It need to be replaced with this then? A Clang-tidy syntax to create the same aniMeshVertex. I found this in pull request #4527 I think it may need to be reviewed too. --- code/PostProcessing/JoinVerticesProcess.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 745ce1a5e..84e742115 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -345,8 +345,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { uniqueVertices.push_back(v); if (hasAnimMeshes) { for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { - Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a); - uniqueAnimatedVertices[animMeshIndex].push_back(v); + uniqueAnimatedVertices[animMeshIndex].emplace_back(pMesh->mAnimMeshes[animMeshIndex], a); } } } else{ From 14186bcd6b994bb0b455fc04a290280da6c0e6a3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 27 Aug 2022 14:07:45 +0200 Subject: [PATCH 2/8] Code cleanup and some new unittests for edgecases. --- code/AssetLib/MMD/MMDPmdParser.h | 1034 ++++++++++++++++-------------- code/Common/Base64.cpp | 17 +- include/assimp/Base64.hpp | 30 +- test/unit/Common/utBase64.cpp | 41 +- 4 files changed, 604 insertions(+), 518 deletions(-) diff --git a/code/AssetLib/MMD/MMDPmdParser.h b/code/AssetLib/MMD/MMDPmdParser.h index 35e4f09d1..95d4d4552 100644 --- a/code/AssetLib/MMD/MMDPmdParser.h +++ b/code/AssetLib/MMD/MMDPmdParser.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,550 +47,595 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "MMDCpp14.h" -namespace pmd -{ - class PmdHeader - { - public: - std::string name; - std::string name_english; - std::string comment; - std::string comment_english; +namespace pmd { - bool Read(std::ifstream* stream) - { - char buffer[256]; - stream->read(buffer, 20); - name = std::string(buffer); - stream->read(buffer, 256); - comment = std::string(buffer); - return true; - } +struct PmdHeader { + std::string name; + std::string name_english; + std::string comment; + std::string comment_english; - bool ReadExtension(std::ifstream* stream) - { - char buffer[256]; - stream->read(buffer, 20); - name_english = std::string(buffer); - stream->read(buffer, 256); - comment_english = std::string(buffer); - return true; - } - }; + PmdHeader() = default; + ~PmdHeader() = default; - class PmdVertex - { - public: - float position[3]; + bool Read(std::ifstream *stream) { + if (stream == nullptr) { + return false; + } + char buffer[256] = {}; + stream->read(buffer, 20); + name = std::string(buffer); + stream->read(buffer, 256); + comment = std::string(buffer); + return true; + } - float normal[3]; + bool ReadExtension(std::ifstream *stream) { + if (stream == nullptr) { + return false; + } - float uv[2]; + char buffer[256] = {}; + stream->read(buffer, 20); + name_english = std::string(buffer); + stream->read(buffer, 256); + comment_english = std::string(buffer); - uint16_t bone_index[2]; + return true; + } +}; - uint8_t bone_weight; +struct PmdVertex { + float position[3]; + float normal[3]; + float uv[2]; + uint16_t bone_index[2]; + uint8_t bone_weight; + bool edge_invisible; - bool edge_invisible; + PmdVertex() : + position{ 0.0f }, normal{ 0.0f }, uv{ 0.0f }, bone_index{ 0 }, bone_weight(0), edge_invisible(false) {} - bool Read(std::ifstream* stream) - { - stream->read((char*) position, sizeof(float) * 3); - stream->read((char*) normal, sizeof(float) * 3); - stream->read((char*) uv, sizeof(float) * 2); - stream->read((char*) bone_index, sizeof(uint16_t) * 2); - stream->read((char*) &bone_weight, sizeof(uint8_t)); - stream->read((char*) &edge_invisible, sizeof(uint8_t)); - return true; - } - }; + ~PmdVertex() = default; - class PmdMaterial - { - public: - float diffuse[4]; - float power; - float specular[3]; - float ambient[3]; - uint8_t toon_index; - uint8_t edge_flag; - uint32_t index_count; - std::string texture_filename; - std::string sphere_filename; + bool Read(std::ifstream *stream) { + if (stream == nullptr) { + return false; + } - bool Read(std::ifstream* stream) - { - char buffer[20]; - stream->read((char*) &diffuse, sizeof(float) * 4); - stream->read((char*) &power, sizeof(float)); - stream->read((char*) &specular, sizeof(float) * 3); - stream->read((char*) &ambient, sizeof(float) * 3); - stream->read((char*) &toon_index, sizeof(uint8_t)); - stream->read((char*) &edge_flag, sizeof(uint8_t)); - stream->read((char*) &index_count, sizeof(uint32_t)); - stream->read((char*) &buffer, sizeof(char) * 20); - char* pstar = strchr(buffer, '*'); - if (nullptr == pstar) - { - texture_filename = std::string(buffer); - sphere_filename.clear(); - } - else { - *pstar = 0; - texture_filename = std::string(buffer); - sphere_filename = std::string(pstar+1); - } - return true; - } - }; + stream->read((char *)position, sizeof(float) * 3); + stream->read((char *)normal, sizeof(float) * 3); + stream->read((char *)uv, sizeof(float) * 2); + stream->read((char *)bone_index, sizeof(uint16_t) * 2); + stream->read((char *)&bone_weight, sizeof(uint8_t)); + stream->read((char *)&edge_invisible, sizeof(uint8_t)); + return true; + } +}; - enum class BoneType : uint8_t - { - Rotation, - RotationAndMove, - IkEffector, - Unknown, - IkEffectable, - RotationEffectable, - IkTarget, - Invisible, - Twist, - RotationMovement - }; +struct PmdMaterial { + float diffuse[4]; + float power; + float specular[3]; + float ambient[3]; + uint8_t toon_index; + uint8_t edge_flag; + uint32_t index_count; + std::string texture_filename; + std::string sphere_filename; - class PmdBone - { - public: - std::string name; - std::string name_english; - uint16_t parent_bone_index; - uint16_t tail_pos_bone_index; - BoneType bone_type; - uint16_t ik_parent_bone_index; - float bone_head_pos[3]; + PmdMaterial() : + diffuse{ 0.0f }, power(0.0f), specular{ 0.0f }, ambient{ 0.0f }, toon_index(0), edge_flag(0), index_count(0), texture_filename(), sphere_filename() {} - void Read(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, 20); - name = std::string(buffer); - stream->read((char*) &parent_bone_index, sizeof(uint16_t)); - stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t)); - stream->read((char*) &bone_type, sizeof(uint8_t)); - stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t)); - stream->read((char*) &bone_head_pos, sizeof(float) * 3); - } + ~PmdMaterial() = default; - void ReadExpantion(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, 20); - name_english = std::string(buffer); - } - }; + bool Read(std::ifstream *stream) { + if (stream == nullptr) { + return false; + } + constexpr size_t BufferSize = 20; - class PmdIk - { - public: - uint16_t ik_bone_index; - uint16_t target_bone_index; - uint16_t iterations; - float angle_limit; - std::vector ik_child_bone_index; + char buffer[BufferSize] = {}; + stream->read((char *)&diffuse, sizeof(float) * 4); + stream->read((char *)&power, sizeof(float)); + stream->read((char *)&specular, sizeof(float) * 3); + stream->read((char *)&ambient, sizeof(float) * 3); + stream->read((char *)&toon_index, sizeof(uint8_t)); + stream->read((char *)&edge_flag, sizeof(uint8_t)); + stream->read((char *)&index_count, sizeof(uint32_t)); + stream->read((char *)&buffer, sizeof(char) * BufferSize); + char *pstar = strchr(buffer, '*'); + if (nullptr == pstar) { + texture_filename = std::string(buffer); + sphere_filename.clear(); + } else { + *pstar = 0; + texture_filename = std::string(buffer); + sphere_filename = std::string(pstar + 1); + } - void Read(std::istream *stream) - { - stream->read((char *) &ik_bone_index, sizeof(uint16_t)); - stream->read((char *) &target_bone_index, sizeof(uint16_t)); - uint8_t ik_chain_length; - stream->read((char*) &ik_chain_length, sizeof(uint8_t)); - stream->read((char *) &iterations, sizeof(uint16_t)); - stream->read((char *) &angle_limit, sizeof(float)); - ik_child_bone_index.resize(ik_chain_length); - for (int i = 0; i < ik_chain_length; i++) - { - stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t)); - } - } - }; + return true; + } +}; - class PmdFaceVertex - { - public: - int vertex_index; - float position[3]; +enum class BoneType : uint8_t { + Rotation, + RotationAndMove, + IkEffector, + Unknown, + IkEffectable, + RotationEffectable, + IkTarget, + Invisible, + Twist, + RotationMovement - void Read(std::istream *stream) - { - stream->read((char *) &vertex_index, sizeof(int)); - stream->read((char *) position, sizeof(float) * 3); - } - }; +}; - enum class FaceCategory : uint8_t - { - Base, - Eyebrow, - Eye, - Mouth, - Other - }; +struct PmdBone { + std::string name; + std::string name_english; + uint16_t parent_bone_index; + uint16_t tail_pos_bone_index; + BoneType bone_type; + uint16_t ik_parent_bone_index; + float bone_head_pos[3]; - class PmdFace - { - public: - std::string name; - FaceCategory type; - std::vector vertices; - std::string name_english; + PmdBone() : + name(), name_english(), parent_bone_index(0), tail_pos_bone_index(0), bone_type(BoneType::Unknown), ik_parent_bone_index(0), bone_head_pos{ 0.0f } {} - void Read(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, 20); - name = std::string(buffer); - int vertex_count; - stream->read((char*) &vertex_count, sizeof(int)); - stream->read((char*) &type, sizeof(uint8_t)); - vertices.resize(vertex_count); - for (int i = 0; i < vertex_count; i++) - { - vertices[i].Read(stream); - } - } + ~PmdBone() = default; - void ReadExpantion(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, 20); - name_english = std::string(buffer); - } - }; + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + constexpr size_t BufferSize = 20; + char buffer[BufferSize] = {}; + stream->read(buffer, BufferSize); + name = std::string(buffer); + stream->read((char *)&parent_bone_index, sizeof(uint16_t)); + stream->read((char *)&tail_pos_bone_index, sizeof(uint16_t)); + stream->read((char *)&bone_type, sizeof(uint8_t)); + stream->read((char *)&ik_parent_bone_index, sizeof(uint16_t)); + stream->read((char *)&bone_head_pos, sizeof(float) * 3); + } - class PmdBoneDispName - { - public: - std::string bone_disp_name; - std::string bone_disp_name_english; + void ReadExpantion(std::istream *stream) { + if (stream == nullptr) { + return; + } + constexpr size_t BufferSize = 20; + char buffer[BufferSize] = {}; + stream->read(buffer, BufferSize); + name_english = std::string(buffer); + } +}; - void Read(std::istream *stream) - { - char buffer[50]; - stream->read(buffer, 50); - bone_disp_name = std::string(buffer); - bone_disp_name_english.clear(); - } - void ReadExpantion(std::istream *stream) - { - char buffer[50]; - stream->read(buffer, 50); - bone_disp_name_english = std::string(buffer); - } - }; +struct PmdIk { + uint16_t ik_bone_index; + uint16_t target_bone_index; + uint16_t iterations; + float angle_limit; + std::vector ik_child_bone_index; - class PmdBoneDisp - { - public: - uint16_t bone_index; - uint8_t bone_disp_index; + PmdIk() : + ik_child_bone_index(0), target_bone_index(0), iterations(0), angle_limit(0.0f) {} - void Read(std::istream *stream) - { - stream->read((char*) &bone_index, sizeof(uint16_t)); - stream->read((char*) &bone_disp_index, sizeof(uint8_t)); - } - }; + ~PmdIk() = default; - enum class RigidBodyShape : uint8_t - { - Sphere = 0, - Box = 1, - Cpusel = 2 - }; + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } - enum class RigidBodyType : uint8_t - { - BoneConnected = 0, - Physics = 1, - ConnectedPhysics = 2 - }; + stream->read((char *)&ik_bone_index, sizeof(uint16_t)); + stream->read((char *)&target_bone_index, sizeof(uint16_t)); + uint8_t ik_chain_length; + stream->read((char *)&ik_chain_length, sizeof(uint8_t)); + stream->read((char *)&iterations, sizeof(uint16_t)); + stream->read((char *)&angle_limit, sizeof(float)); + ik_child_bone_index.resize(ik_chain_length); + for (int i = 0; i < ik_chain_length; i++) { + stream->read((char *)&ik_child_bone_index[i], sizeof(uint16_t)); + } + } +}; - class PmdRigidBody - { - public: - std::string name; - uint16_t related_bone_index; - uint8_t group_index; - uint16_t mask; - RigidBodyShape shape; - float size[3]; - float position[3]; - float orientation[3]; - float weight; - float linear_damping; - float anglar_damping; - float restitution; - float friction; - RigidBodyType rigid_type; +struct PmdFaceVertex { + int vertex_index; + float position[3]; - void Read(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, sizeof(char) * 20); - name = (std::string(buffer)); - stream->read((char*) &related_bone_index, sizeof(uint16_t)); - stream->read((char*) &group_index, sizeof(uint8_t)); - stream->read((char*) &mask, sizeof(uint16_t)); - stream->read((char*) &shape, sizeof(uint8_t)); - stream->read((char*) size, sizeof(float) * 3); - stream->read((char*) position, sizeof(float) * 3); - stream->read((char*) orientation, sizeof(float) * 3); - stream->read((char*) &weight, sizeof(float)); - stream->read((char*) &linear_damping, sizeof(float)); - stream->read((char*) &anglar_damping, sizeof(float)); - stream->read((char*) &restitution, sizeof(float)); - stream->read((char*) &friction, sizeof(float)); - stream->read((char*) &rigid_type, sizeof(char)); - } - }; + PmdFaceVertex() : + vertex_index(0), position{ 0.0f } {} - class PmdConstraint - { - public: - std::string name; - uint32_t rigid_body_index_a; - uint32_t rigid_body_index_b; - float position[3]; - float orientation[3]; - float linear_lower_limit[3]; - float linear_upper_limit[3]; - float angular_lower_limit[3]; - float angular_upper_limit[3]; - float linear_stiffness[3]; - float angular_stiffness[3]; + ~PmdFaceVertex() = default; - void Read(std::istream *stream) - { - char buffer[20]; - stream->read(buffer, 20); - name = std::string(buffer); - stream->read((char *) &rigid_body_index_a, sizeof(uint32_t)); - stream->read((char *) &rigid_body_index_b, sizeof(uint32_t)); - stream->read((char *) position, sizeof(float) * 3); - stream->read((char *) orientation, sizeof(float) * 3); - stream->read((char *) linear_lower_limit, sizeof(float) * 3); - stream->read((char *) linear_upper_limit, sizeof(float) * 3); - stream->read((char *) angular_lower_limit, sizeof(float) * 3); - stream->read((char *) angular_upper_limit, sizeof(float) * 3); - stream->read((char *) linear_stiffness, sizeof(float) * 3); - stream->read((char *) angular_stiffness, sizeof(float) * 3); - } - }; + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + stream->read((char *)&vertex_index, sizeof(int)); + stream->read((char *)position, sizeof(float) * 3); + } +}; - class PmdModel - { - public: - float version; - PmdHeader header; - std::vector vertices; - std::vector indices; - std::vector materials; - std::vector bones; - std::vector iks; - std::vector faces; - std::vector faces_indices; - std::vector bone_disp_name; - std::vector bone_disp; - std::vector toon_filenames; - std::vector rigid_bodies; - std::vector constraints; +enum class FaceCategory : uint8_t { + Base, + Eyebrow, + Eye, + Mouth, + Other +}; - static std::unique_ptr LoadFromFile(const char *filename) - { - std::ifstream stream(filename, std::ios::binary); - if (stream.fail()) - { - std::cerr << "could not open \"" << filename << "\"" << std::endl; - return nullptr; - } - auto result = LoadFromStream(&stream); - stream.close(); - return result; - } +struct PmdFace { + std::string name; + FaceCategory type; + std::vector vertices; + std::string name_english; - static std::unique_ptr LoadFromStream(std::ifstream *stream) - { - auto result = mmd::make_unique(); - char buffer[100]; + PmdFace() : + name(), type(FaceCategory::Other), vertices(), name_english() {} - // magic - char magic[3]; - stream->read(magic, 3); - if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd') - { - std::cerr << "invalid file" << std::endl; - return nullptr; - } + ~PmdFace() = default; - // version - stream->read((char*) &(result->version), sizeof(float)); - if (result ->version != 1.0f) - { - std::cerr << "invalid version" << std::endl; - return nullptr; - } + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + constexpr size_t BufferSize = 20; + char buffer[BufferSize]; + stream->read(buffer, BufferSize); + name = std::string(buffer); + int vertex_count; + stream->read((char *)&vertex_count, sizeof(int)); + stream->read((char *)&type, sizeof(uint8_t)); + vertices.resize(vertex_count); + for (int i = 0; i < vertex_count; i++) { + vertices[i].Read(stream); + } + } - // header - result->header.Read(stream); + void ReadExpantion(std::istream *stream) { + if (stream == nullptr) { + return; + } - // vertices - uint32_t vertex_num; - stream->read((char*) &vertex_num, sizeof(uint32_t)); - result->vertices.resize(vertex_num); - for (uint32_t i = 0; i < vertex_num; i++) - { - result->vertices[i].Read(stream); - } + char buffer[20]; + stream->read(buffer, 20); + name_english = std::string(buffer); + } +}; - // indices - uint32_t index_num; - stream->read((char*) &index_num, sizeof(uint32_t)); - result->indices.resize(index_num); - for (uint32_t i = 0; i < index_num; i++) - { - stream->read((char*) &result->indices[i], sizeof(uint16_t)); - } +struct PmdBoneDispName { + std::string bone_disp_name; + std::string bone_disp_name_english; - // materials - uint32_t material_num; - stream->read((char*) &material_num, sizeof(uint32_t)); - result->materials.resize(material_num); - for (uint32_t i = 0; i < material_num; i++) - { - result->materials[i].Read(stream); - } + PmdBoneDispName() = default; - // bones - uint16_t bone_num; - stream->read((char*) &bone_num, sizeof(uint16_t)); - result->bones.resize(bone_num); - for (uint32_t i = 0; i < bone_num; i++) - { - result->bones[i].Read(stream); - } + ~PmdBoneDispName() = default; - // iks - uint16_t ik_num; - stream->read((char*) &ik_num, sizeof(uint16_t)); - result->iks.resize(ik_num); - for (uint32_t i = 0; i < ik_num; i++) - { - result->iks[i].Read(stream); - } + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + char buffer[50]; + stream->read(buffer, 50); + bone_disp_name = std::string(buffer); + bone_disp_name_english.clear(); + } - // faces - uint16_t face_num; - stream->read((char*) &face_num, sizeof(uint16_t)); - result->faces.resize(face_num); - for (uint32_t i = 0; i < face_num; i++) - { - result->faces[i].Read(stream); - } + void ReadExpantion(std::istream *stream) { + if (stream == nullptr) { + return; + } + char buffer[50]; + stream->read(buffer, 50); + bone_disp_name_english = std::string(buffer); + } +}; - // face frames - uint8_t face_frame_num; - stream->read((char*) &face_frame_num, sizeof(uint8_t)); - result->faces_indices.resize(face_frame_num); - for (uint32_t i = 0; i < face_frame_num; i++) - { - stream->read((char*) &result->faces_indices[i], sizeof(uint16_t)); - } +struct PmdBoneDisp { + uint16_t bone_index; + uint8_t bone_disp_index; - // bone names - uint8_t bone_disp_num; - stream->read((char*) &bone_disp_num, sizeof(uint8_t)); - result->bone_disp_name.resize(bone_disp_num); - for (uint32_t i = 0; i < bone_disp_num; i++) - { - result->bone_disp_name[i].Read(stream); - } + PmdBoneDisp() : + bone_index(0), bone_disp_index(0) {} - // bone frame - uint32_t bone_frame_num; - stream->read((char*) &bone_frame_num, sizeof(uint32_t)); - result->bone_disp.resize(bone_frame_num); - for (uint32_t i = 0; i < bone_frame_num; i++) - { - result->bone_disp[i].Read(stream); - } + ~PmdBoneDisp() = default; - // english name - bool english; - stream->read((char*) &english, sizeof(char)); - if (english) - { - result->header.ReadExtension(stream); - for (uint32_t i = 0; i < bone_num; i++) - { - result->bones[i].ReadExpantion(stream); - } - for (uint32_t i = 0; i < face_num; i++) - { - if (result->faces[i].type == pmd::FaceCategory::Base) - { - continue; - } - result->faces[i].ReadExpantion(stream); - } - for (uint32_t i = 0; i < result->bone_disp_name.size(); i++) - { - result->bone_disp_name[i].ReadExpantion(stream); - } - } + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } - // toon textures - if (stream->peek() == std::ios::traits_type::eof()) - { - result->toon_filenames.clear(); - } - else { - result->toon_filenames.resize(10); - for (uint32_t i = 0; i < 10; i++) - { - stream->read(buffer, 100); - result->toon_filenames[i] = std::string(buffer); - } - } + stream->read((char *)&bone_index, sizeof(uint16_t)); + stream->read((char *)&bone_disp_index, sizeof(uint8_t)); + } +}; - // physics - if (stream->peek() == std::ios::traits_type::eof()) - { - result->rigid_bodies.clear(); - result->constraints.clear(); - } - else { - uint32_t rigid_body_num; - stream->read((char*) &rigid_body_num, sizeof(uint32_t)); - result->rigid_bodies.resize(rigid_body_num); - for (uint32_t i = 0; i < rigid_body_num; i++) - { - result->rigid_bodies[i].Read(stream); - } - uint32_t constraint_num; - stream->read((char*) &constraint_num, sizeof(uint32_t)); - result->constraints.resize(constraint_num); - for (uint32_t i = 0; i < constraint_num; i++) - { - result->constraints[i].Read(stream); - } - } +enum class RigidBodyShape : uint8_t { + Sphere = 0, + Box = 1, + Cpusel = 2 +}; - if (stream->peek() != std::ios::traits_type::eof()) - { - std::cerr << "there is unknown data" << std::endl; - } +enum class RigidBodyType : uint8_t { + BoneConnected = 0, + Physics = 1, + ConnectedPhysics = 2 +}; + +struct PmdRigidBody { + std::string name; + uint16_t related_bone_index; + uint8_t group_index; + uint16_t mask; + RigidBodyShape shape; + float size[3]; + float position[3]; + float orientation[3]; + float weight; + float linear_damping; + float anglar_damping; + float restitution; + float friction; + RigidBodyType rigid_type; + + PmdRigidBody() : + name(), related_bone_index(0), group_index(0), mask(0), shape(RigidBodyShape::Box), size{ 0.0f }, position{ 0.0f }, weight(0.0f), linear_damping(0.0f), anglar_damping(0.0f), restitution(0.0f), friction(0.0f), rigid_type(RigidBodyType::BoneConnected) {} + + ~PmdRigidBody() = default; + + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + + char buffer[20]; + stream->read(buffer, sizeof(char) * 20); + name = (std::string(buffer)); + stream->read((char *)&related_bone_index, sizeof(uint16_t)); + stream->read((char *)&group_index, sizeof(uint8_t)); + stream->read((char *)&mask, sizeof(uint16_t)); + stream->read((char *)&shape, sizeof(uint8_t)); + stream->read((char *)size, sizeof(float) * 3); + stream->read((char *)position, sizeof(float) * 3); + stream->read((char *)orientation, sizeof(float) * 3); + stream->read((char *)&weight, sizeof(float)); + stream->read((char *)&linear_damping, sizeof(float)); + stream->read((char *)&anglar_damping, sizeof(float)); + stream->read((char *)&restitution, sizeof(float)); + stream->read((char *)&friction, sizeof(float)); + stream->read((char *)&rigid_type, sizeof(char)); + } +}; + +struct PmdConstraint { + std::string name; + uint32_t rigid_body_index_a; + uint32_t rigid_body_index_b; + float position[3]; + float orientation[3]; + float linear_lower_limit[3]; + float linear_upper_limit[3]; + float angular_lower_limit[3]; + float angular_upper_limit[3]; + float linear_stiffness[3]; + float angular_stiffness[3]; + + PmdConstraint() : + name(), rigid_body_index_a(0), rigid_body_index_b(0), position{ 0.0f }, orientation{ 0.0f }, linear_lower_limit{ 0.0f }, linear_upper_limit{ 0.0f }, angular_lower_limit{ 0.0f }, angular_upper_limit{ 0.0f }, linear_stiffness{ 0.0f }, angular_stiffness{ 0.0f } {} + + ~PmdConstraint() = default; + + void Read(std::istream *stream) { + if (stream == nullptr) { + return; + } + + char buffer[20]; + stream->read(buffer, 20); + name = std::string(buffer); + stream->read((char *)&rigid_body_index_a, sizeof(uint32_t)); + stream->read((char *)&rigid_body_index_b, sizeof(uint32_t)); + stream->read((char *)position, sizeof(float) * 3); + stream->read((char *)orientation, sizeof(float) * 3); + stream->read((char *)linear_lower_limit, sizeof(float) * 3); + stream->read((char *)linear_upper_limit, sizeof(float) * 3); + stream->read((char *)angular_lower_limit, sizeof(float) * 3); + stream->read((char *)angular_upper_limit, sizeof(float) * 3); + stream->read((char *)linear_stiffness, sizeof(float) * 3); + stream->read((char *)angular_stiffness, sizeof(float) * 3); + } +}; + +struct PmdModel { + float version; + PmdHeader header; + std::vector vertices; + std::vector indices; + std::vector materials; + std::vector bones; + std::vector iks; + std::vector faces; + std::vector faces_indices; + std::vector bone_disp_name; + std::vector bone_disp; + std::vector toon_filenames; + std::vector rigid_bodies; + std::vector constraints; + + PmdModel() : + version(0.0f) {} + + ~PmdModel() = default; + + static std::unique_ptr LoadFromFile(const char *filename) { + if (filename == nullptr) { + return nullptr; + } + + std::ifstream stream(filename, std::ios::binary); + if (stream.fail()) { + std::cerr << "could not open \"" << filename << "\"" << std::endl; + return nullptr; + } + auto result = LoadFromStream(&stream); + stream.close(); + return result; + } + + static std::unique_ptr LoadFromStream(std::ifstream *stream) { + auto result = mmd::make_unique(); + char buffer[100]; + + // magic + char magic[3]; + stream->read(magic, 3); + if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd') { + std::cerr << "invalid file" << std::endl; + return nullptr; + } + + // version + stream->read((char *)&(result->version), sizeof(float)); + if (result->version != 1.0f) { + std::cerr << "invalid version" << std::endl; + return nullptr; + } + + // header + result->header.Read(stream); + + // vertices + uint32_t vertex_num; + stream->read((char *)&vertex_num, sizeof(uint32_t)); + result->vertices.resize(vertex_num); + for (uint32_t i = 0; i < vertex_num; i++) { + result->vertices[i].Read(stream); + } + + // indices + uint32_t index_num; + stream->read((char *)&index_num, sizeof(uint32_t)); + result->indices.resize(index_num); + for (uint32_t i = 0; i < index_num; i++) { + stream->read((char *)&result->indices[i], sizeof(uint16_t)); + } + + // materials + uint32_t material_num; + stream->read((char *)&material_num, sizeof(uint32_t)); + result->materials.resize(material_num); + for (uint32_t i = 0; i < material_num; i++) { + result->materials[i].Read(stream); + } + + // bones + uint16_t bone_num; + stream->read((char *)&bone_num, sizeof(uint16_t)); + result->bones.resize(bone_num); + for (uint32_t i = 0; i < bone_num; i++) { + result->bones[i].Read(stream); + } + + // iks + uint16_t ik_num; + stream->read((char *)&ik_num, sizeof(uint16_t)); + result->iks.resize(ik_num); + for (uint32_t i = 0; i < ik_num; i++) { + result->iks[i].Read(stream); + } + + // faces + uint16_t face_num; + stream->read((char *)&face_num, sizeof(uint16_t)); + result->faces.resize(face_num); + for (uint32_t i = 0; i < face_num; i++) { + result->faces[i].Read(stream); + } + + // face frames + uint8_t face_frame_num; + stream->read((char *)&face_frame_num, sizeof(uint8_t)); + result->faces_indices.resize(face_frame_num); + for (uint32_t i = 0; i < face_frame_num; i++) { + stream->read((char *)&result->faces_indices[i], sizeof(uint16_t)); + } + + // bone names + uint8_t bone_disp_num; + stream->read((char *)&bone_disp_num, sizeof(uint8_t)); + result->bone_disp_name.resize(bone_disp_num); + for (uint32_t i = 0; i < bone_disp_num; i++) { + result->bone_disp_name[i].Read(stream); + } + + // bone frame + uint32_t bone_frame_num; + stream->read((char *)&bone_frame_num, sizeof(uint32_t)); + result->bone_disp.resize(bone_frame_num); + for (uint32_t i = 0; i < bone_frame_num; i++) { + result->bone_disp[i].Read(stream); + } + + // english name + bool english; + stream->read((char *)&english, sizeof(char)); + if (english) { + result->header.ReadExtension(stream); + for (uint32_t i = 0; i < bone_num; i++) { + result->bones[i].ReadExpantion(stream); + } + for (uint32_t i = 0; i < face_num; i++) { + if (result->faces[i].type == pmd::FaceCategory::Base) { + continue; + } + result->faces[i].ReadExpantion(stream); + } + for (uint32_t i = 0; i < result->bone_disp_name.size(); i++) { + result->bone_disp_name[i].ReadExpantion(stream); + } + } + + // toon textures + if (stream->peek() == std::ios::traits_type::eof()) { + result->toon_filenames.clear(); + } else { + result->toon_filenames.resize(10); + for (uint32_t i = 0; i < 10; i++) { + stream->read(buffer, 100); + result->toon_filenames[i] = std::string(buffer); + } + } + + // physics + if (stream->peek() == std::ios::traits_type::eof()) { + result->rigid_bodies.clear(); + result->constraints.clear(); + } else { + uint32_t rigid_body_num; + stream->read((char *)&rigid_body_num, sizeof(uint32_t)); + result->rigid_bodies.resize(rigid_body_num); + for (uint32_t i = 0; i < rigid_body_num; i++) { + result->rigid_bodies[i].Read(stream); + } + uint32_t constraint_num; + stream->read((char *)&constraint_num, sizeof(uint32_t)); + result->constraints.resize(constraint_num); + for (uint32_t i = 0; i < constraint_num; i++) { + result->constraints[i].Read(stream); + } + } + + if (stream->peek() != std::ios::traits_type::eof()) { + std::cerr << "there is unknown data" << std::endl; + } + + return result; + } +}; + +} // namespace pmd - return result; - } - }; -} diff --git a/code/Common/Base64.cpp b/code/Common/Base64.cpp index 3e9c47405..e55e0ba75 100644 --- a/code/Common/Base64.cpp +++ b/code/Common/Base64.cpp @@ -46,7 +46,7 @@ namespace Assimp { namespace Base64 { -static const uint8_t tableDecodeBase64[128] = { +static constexpr uint8_t tableDecodeBase64[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, @@ -57,7 +57,7 @@ static const uint8_t tableDecodeBase64[128] = { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0 }; -static const char *tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +static constexpr char *tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; static inline char EncodeChar(uint8_t b) { return tableEncodeBase64[size_t(b)]; @@ -71,6 +71,11 @@ inline uint8_t DecodeChar(char c) { } void Encode(const uint8_t *in, size_t inLength, std::string &out) { + if (in == nullptr || inLength==0) { + out.clear(); + return; + } + size_t outLength = ((inLength + 2) / 3) * 4; size_t j = out.size(); @@ -115,8 +120,14 @@ std::string Encode(const std::vector &in) { } size_t Decode(const char *in, size_t inLength, uint8_t *&out) { + if (in == nullptr) { + out = nullptr; + return 0; + } + if (inLength % 4 != 0) { - throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), "\", length:", inLength); + throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), + "\", length:", inLength); } if (inLength < 4) { diff --git a/include/assimp/Base64.hpp b/include/assimp/Base64.hpp index ee319aceb..403723857 100644 --- a/include/assimp/Base64.hpp +++ b/include/assimp/Base64.hpp @@ -50,16 +50,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace Base64 { -/// @brief Will encode the given -/// @param in -/// @param inLength -/// @param out +/// @brief Will encode the given character buffer from UTF64 to ASCII +/// @param in The UTF-64 buffer. +/// @param inLength The size of the buffer +/// @param out The encoded ASCII string. void Encode(const uint8_t *in, size_t inLength, std::string &out); + +/// @brief Will encode the given character buffer from UTF64 to ASCII. +/// @param in A vector, which contains the buffer for encoding. +/// @param out The encoded ASCII string. void Encode(const std::vector& in, std::string &out); + +/// @brief Will encode the given character buffer from UTF64 to ASCII. +/// @param in A vector, which contains the buffer for encoding. +/// @return The encoded ASCII string. std::string Encode(const std::vector& in); +/// @brief Will decode the given character buffer from ASCII to UTF64. +/// @param in The ASCII buffer to decode. +/// @param inLength The size of the buffer. +/// @param out The decoded buffer. +/// @return The new buffer size. size_t Decode(const char *in, size_t inLength, uint8_t *&out); + +/// @brief Will decode the given character buffer from ASCII to UTF64. +/// @param in The ASCII buffer to decode as a std::string. +/// @param out The decoded buffer. +/// @return The new buffer size. size_t Decode(const std::string& in, std::vector& out); + +/// @brief Will decode the given character buffer from ASCII to UTF64. +/// @param in The ASCII string. +/// @return The decoded buffer in a vector. std::vector Decode(const std::string& in); } // namespace Base64 diff --git a/test/unit/Common/utBase64.cpp b/test/unit/Common/utBase64.cpp index 8b0a60e47..ec927b980 100644 --- a/test/unit/Common/utBase64.cpp +++ b/test/unit/Common/utBase64.cpp @@ -47,26 +47,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace std; using namespace Assimp; -class Base64Test : public ::testing::Test { -public: - virtual void SetUp() { - } - - virtual void TearDown() { - } -}; +class Base64Test : public ::testing::Test {}; static const std::vector assimpStringBinary = { 97, 115, 115, 105, 109, 112 }; static const std::string assimpStringEncoded = "YXNzaW1w"; -TEST_F( Base64Test, encodeTest ) { - EXPECT_EQ( "", Base64::Encode (std::vector{}) ); - EXPECT_EQ( "Vg==", Base64::Encode (std::vector{ 86 }) ); - EXPECT_EQ( assimpStringEncoded, Base64::Encode (assimpStringBinary) ); +TEST_F( Base64Test, encodeTest) { + EXPECT_EQ( "", Base64::Encode(std::vector{}) ); + EXPECT_EQ( "Vg==", Base64::Encode(std::vector{ 86 }) ); + EXPECT_EQ( assimpStringEncoded, Base64::Encode(assimpStringBinary) ); } -TEST_F( Base64Test, decodeTest ) { - EXPECT_EQ( std::vector {}, Base64::Decode ("") ); - EXPECT_EQ( std::vector { 86 }, Base64::Decode ("Vg==") ); - EXPECT_EQ( assimpStringBinary, Base64::Decode (assimpStringEncoded) ); +TEST_F( Base64Test, encodeTestWithNullptr ) { + std::string out; + Base64::Encode(nullptr, 100u, out); + EXPECT_TRUE(out.empty()); + + Base64::Encode(&assimpStringBinary[0], 0u, out); + EXPECT_TRUE(out.empty()); +} + +TEST_F( Base64Test, decodeTest) { + EXPECT_EQ( std::vector {}, Base64::Decode("") ); + EXPECT_EQ( std::vector { 86 }, Base64::Decode("Vg==") ); + EXPECT_EQ( assimpStringBinary, Base64::Decode(assimpStringEncoded) ); +} + +TEST_F(Base64Test, decodeTestWithNullptr) { + uint8_t *out = nullptr; + size_t size = Base64::Decode(nullptr, 100u, out); + EXPECT_EQ(nullptr, out); + EXPECT_EQ(0u, size); } From e4c383324a61794251b729b4dff75433ff9b6b1b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 27 Aug 2022 15:11:54 +0200 Subject: [PATCH 3/8] Use string for constexpr --- code/Common/Base64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/Base64.cpp b/code/Common/Base64.cpp index e55e0ba75..65308f4fd 100644 --- a/code/Common/Base64.cpp +++ b/code/Common/Base64.cpp @@ -57,7 +57,7 @@ static constexpr uint8_t tableDecodeBase64[128] = { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0 }; -static constexpr char *tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +static constexpr char tableEncodeBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; static inline char EncodeChar(uint8_t b) { return tableEncodeBase64[size_t(b)]; From 02e6c425f9b06dbd5e6fb019555beee2caa980de Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 27 Aug 2022 15:20:53 +0200 Subject: [PATCH 4/8] Fix ordering of initalizer list --- code/AssetLib/MMD/MMDPmdParser.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/AssetLib/MMD/MMDPmdParser.h b/code/AssetLib/MMD/MMDPmdParser.h index 95d4d4552..23aaac555 100644 --- a/code/AssetLib/MMD/MMDPmdParser.h +++ b/code/AssetLib/MMD/MMDPmdParser.h @@ -219,8 +219,7 @@ struct PmdIk { float angle_limit; std::vector ik_child_bone_index; - PmdIk() : - ik_child_bone_index(0), target_bone_index(0), iterations(0), angle_limit(0.0f) {} + PmdIk() : ik_bone_index(0), target_bone_index(0), iterations(0), angle_limit(0.0f) {} ~PmdIk() = default; From 0571ee21fb97b3b509d999b0d35d10347fbae40b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 28 Aug 2022 20:58:52 +0200 Subject: [PATCH 5/8] Introduce unittest for BaseProcess. --- code/Common/AssertHandler.cpp | 20 +++--- code/Common/AssertHandler.h | 46 +++++++------ code/Common/BaseImporter.cpp | 14 ++-- code/Common/BaseProcess.cpp | 13 +++- code/Common/BaseProcess.h | 44 ++++++------ test/CMakeLists.txt | 3 +- test/unit/Common/utBaseProcess.cpp | 105 +++++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 60 deletions(-) create mode 100644 test/unit/Common/utBaseProcess.cpp diff --git a/code/Common/AssertHandler.cpp b/code/Common/AssertHandler.cpp index d0bd6ccad..469e7bec5 100644 --- a/code/Common/AssertHandler.cpp +++ b/code/Common/AssertHandler.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -50,23 +48,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -void Assimp::defaultAiAssertHandler(const char* failedExpression, const char* file, int line) -{ +void Assimp::defaultAiAssertHandler(const char* failedExpression, const char* file, int line) { std::cerr << "ai_assert failure in " << file << "(" << line << "): " << failedExpression << std::endl; std::abort(); } -namespace -{ +namespace { Assimp::AiAssertHandler s_handler = Assimp::defaultAiAssertHandler; } -void Assimp::setAiAssertHandler(AiAssertHandler handler) -{ - s_handler = handler; +void Assimp::setAiAssertHandler(AiAssertHandler handler) { + if (handler != nullptr) { + s_handler = handler; + } else { + s_handler = Assimp::defaultAiAssertHandler; + } } -void Assimp::aiAssertViolation(const char* failedExpression, const char* file, int line) -{ +void Assimp::aiAssertViolation(const char* failedExpression, const char* file, int line) { s_handler(failedExpression, file, line); } diff --git a/code/Common/AssertHandler.h b/code/Common/AssertHandler.h index 2515f0bf2..365a924b0 100644 --- a/code/Common/AssertHandler.h +++ b/code/Common/AssertHandler.h @@ -47,29 +47,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ - // --------------------------------------------------------------------------- - /** Signature of functions which handle assert violations. - */ - using AiAssertHandler = void (*)(const char* failedExpression, const char* file, int line); +namespace Assimp { - // --------------------------------------------------------------------------- - /** Set the assert handler. - */ - ASSIMP_API void setAiAssertHandler(AiAssertHandler handler); +// --------------------------------------------------------------------------- +/** + * @brief Signature of functions which handle assert violations. + */ +using AiAssertHandler = void (*)(const char* failedExpression, const char* file, int line); - // --------------------------------------------------------------------------- - /** The assert handler which is set by default. - * - * This issues a message to stderr and calls abort. - */ - ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line); +// --------------------------------------------------------------------------- +/** + * @brief Set the assert handler. + */ +ASSIMP_API void setAiAssertHandler(AiAssertHandler handler); + +// --------------------------------------------------------------------------- +/** The assert handler which is set by default. + * + * @brief This issues a message to stderr and calls abort. + */ +ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line); + +// --------------------------------------------------------------------------- +/** + * @brief Dispatches an assert violation to the assert handler. + */ +ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line); - // --------------------------------------------------------------------------- - /** Dispatches an assert violation to the assert handler. - */ - ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line); } // end of namespace Assimp -#endif // INCLUDED_AI_ASSERTHANDLER_H \ No newline at end of file +#endif // INCLUDED_AI_ASSERTHANDLER_H diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 383300ef1..1d0aea6a3 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -234,19 +234,23 @@ void BaseImporter::GetExtensionList(std::set &extensions) { std::string::size_type pos = pFile.find_last_of('.'); // no file extension - can't read - if (pos == std::string::npos) + if (pos == std::string::npos) { return false; + } const char *ext_real = &pFile[pos + 1]; - if (!ASSIMP_stricmp(ext_real, ext0)) + if (!ASSIMP_stricmp(ext_real, ext0)) { return true; + } // check for other, optional, file extensions - if (ext1 && !ASSIMP_stricmp(ext_real, ext1)) + if (ext1 && !ASSIMP_stricmp(ext_real, ext1)) { return true; + } - if (ext2 && !ASSIMP_stricmp(ext_real, ext2)) - return true; + if (ext2 && !ASSIMP_stricmp(ext_real, ext2)) { + return true; + } return false; } diff --git a/code/Common/BaseProcess.cpp b/code/Common/BaseProcess.cpp index 48895b9f3..32e9ad608 100644 --- a/code/Common/BaseProcess.cpp +++ b/code/Common/BaseProcess.cpp @@ -66,17 +66,26 @@ BaseProcess::~BaseProcess() { // ------------------------------------------------------------------------------------------------ void BaseProcess::ExecuteOnScene(Importer *pImp) { ai_assert( nullptr != pImp ); - ai_assert( nullptr != pImp->Pimpl()->mScene); + if (pImp == nullptr) { + return; + } + + ai_assert(nullptr != pImp->Pimpl()->mScene); + if (pImp->Pimpl()->mScene == nullptr) { + return; + } progress = pImp->GetProgressHandler(); ai_assert(nullptr != progress); + if (progress == nullptr) { + return; + } SetupProperties(pImp); // catch exceptions thrown inside the PostProcess-Step try { Execute(pImp->Pimpl()->mScene); - } catch (const std::exception &err) { // extract error description diff --git a/code/Common/BaseProcess.h b/code/Common/BaseProcess.h index 64403567a..cd9a43b6b 100644 --- a/code/Common/BaseProcess.h +++ b/code/Common/BaseProcess.h @@ -179,19 +179,20 @@ class ASSIMP_API_WINONLY BaseProcess { friend class Importer; public: - /** Constructor to be privately used by Importer */ + /** @brief onstructor to be privately used by Importer */ BaseProcess() AI_NO_EXCEPT; - /** Destructor, private as well */ + /** @brief Destructor, private as well */ virtual ~BaseProcess(); // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. + /** + * @brief Returns whether the processing step is present in the given flag. * @param pFlags The processing flags the importer was called with. A * bitwise combination of #aiPostProcessSteps. * @return true if the process is present in this flag fields, * false if not. - */ + */ virtual bool IsActive(unsigned int pFlags) const = 0; // ------------------------------------------------------------------- @@ -200,33 +201,36 @@ public: virtual bool RequireVerboseFormat() const; // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * The function deletes the scene if the postprocess step fails ( - * the object pointer will be set to nullptr). - * @param pImp Importer instance (pImp->mScene must be valid) - */ + /** + * @brief Executes the post processing step on the given imported data. + * The function deletes the scene if the post-process step fails ( + * the object pointer will be set to nullptr). + * @param pImp Importer instance (pImp->mScene must be valid) + */ void ExecuteOnScene(Importer *pImp); // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ + /** + * @brief Called prior to ExecuteOnScene(). + * The function is a request to the process to update its configuration + * basing on the Importer's configuration property list. + */ virtual void SetupProperties(const Importer *pImp); // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * A process should throw an ImportErrorException* if it fails. - * This method must be implemented by deriving classes. - * @param pScene The imported data to work at. - */ + /** + * @brief Executes the post processing step on the given imported data. + * A process should throw an ImportErrorException* if it fails. + * This method must be implemented by deriving classes. + * @param pScene The imported data to work at. + */ virtual void Execute(aiScene *pScene) = 0; // ------------------------------------------------------------------- /** Assign a new SharedPostProcessInfo to the step. This object - * allows multiple postprocess steps to share data. + * allows multiple post-process steps to share data. * @param sh May be nullptr - */ + */ inline void SetSharedData(SharedPostProcessInfo *sh) { shared = sh; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cdf13d778..5c87dabbe 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -71,7 +71,6 @@ SET( COMMON unit/AssimpAPITest_aiQuaternion.cpp unit/AssimpAPITest_aiVector2D.cpp unit/AssimpAPITest_aiVector3D.cpp - unit/Common/utHash.cpp unit/MathTest.cpp unit/MathTest.h unit/RandomNumberGeneration.h @@ -98,6 +97,8 @@ SET( COMMON unit/Common/utAssertHandler.cpp unit/Common/utXmlParser.cpp unit/Common/utBase64.cpp + unit/Common/utHash.cpp + unit/Common/utBaseProcess.cpp ) SET( IMPORTERS diff --git a/test/unit/Common/utBaseProcess.cpp b/test/unit/Common/utBaseProcess.cpp new file mode 100644 index 000000000..2da5c18b0 --- /dev/null +++ b/test/unit/Common/utBaseProcess.cpp @@ -0,0 +1,105 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "TestIOSystem.h" +#include "UnitTestPCH.h" + +#include "Common/BaseProcess.h" +#include "Common/AssertHandler.h" + +using namespace Assimp; + +class BaseProcessTest : public ::testing::Test { +public: + static void test_handler( const char*, const char*, int ) { + HandlerWasCalled = true; + } + + void SetUp() override { + HandlerWasCalled = false; + setAiAssertHandler(test_handler); + } + + void TearDown() override { + setAiAssertHandler(nullptr); + } + + static bool handlerWasCalled() { + return HandlerWasCalled; + } + +private: + static bool HandlerWasCalled; +}; + +bool BaseProcessTest::HandlerWasCalled = false; + +class TestingBaseProcess : public BaseProcess { +public: + TestingBaseProcess() : BaseProcess() { + // empty + } + + ~TestingBaseProcess() override = default; + + bool IsActive( unsigned int ) const override { + return true; + } + + void Execute(aiScene*) override { + + } +}; +TEST_F( BaseProcessTest, constructTest ) { + bool ok = true; + try { + TestingBaseProcess process; + } catch (...) { + ok = false; + } + EXPECT_TRUE(ok); +} + +TEST_F( BaseProcessTest, executeOnSceneTest ) { + TestingBaseProcess process; + process.ExecuteOnScene(nullptr); + EXPECT_TRUE(BaseProcessTest::handlerWasCalled()); +} From e34becff62301a57341d9c6d2c83fa6f6f8e24c8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Aug 2022 11:43:32 +0200 Subject: [PATCH 6/8] Enable portable linkage to fix build --- code/Common/BaseProcess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/BaseProcess.h b/code/Common/BaseProcess.h index cd9a43b6b..b6b1e1144 100644 --- a/code/Common/BaseProcess.h +++ b/code/Common/BaseProcess.h @@ -175,7 +175,7 @@ private: * should be executed. If the function returns true, the class' Execute() * function is called subsequently. */ -class ASSIMP_API_WINONLY BaseProcess { +class ASSIMP_API BaseProcess { friend class Importer; public: From 6539b8685fa5cc79b9e140e12f84a88e984ff288 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Aug 2022 17:48:57 +0200 Subject: [PATCH 7/8] Update utBaseProcess.cpp --- test/unit/Common/utBaseProcess.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/Common/utBaseProcess.cpp b/test/unit/Common/utBaseProcess.cpp index 2da5c18b0..004267c2c 100644 --- a/test/unit/Common/utBaseProcess.cpp +++ b/test/unit/Common/utBaseProcess.cpp @@ -101,5 +101,10 @@ TEST_F( BaseProcessTest, constructTest ) { TEST_F( BaseProcessTest, executeOnSceneTest ) { TestingBaseProcess process; process.ExecuteOnScene(nullptr); +#ifdef DEBUG EXPECT_TRUE(BaseProcessTest::handlerWasCalled()); +#else + EXPECT_FALSE(BaseProcessTest::handlerWasCalled()); +#endif + } From fbb69df8be18c5a8c4403813d037b6eadd93ec6a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 30 Aug 2022 20:54:23 +0200 Subject: [PATCH 8/8] Update utBaseProcess.cpp --- test/unit/Common/utBaseProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/Common/utBaseProcess.cpp b/test/unit/Common/utBaseProcess.cpp index 004267c2c..978af7e99 100644 --- a/test/unit/Common/utBaseProcess.cpp +++ b/test/unit/Common/utBaseProcess.cpp @@ -101,7 +101,7 @@ TEST_F( BaseProcessTest, constructTest ) { TEST_F( BaseProcessTest, executeOnSceneTest ) { TestingBaseProcess process; process.ExecuteOnScene(nullptr); -#ifdef DEBUG +#ifdef ASSIMP_BUILD_DEBUG EXPECT_TRUE(BaseProcessTest::handlerWasCalled()); #else EXPECT_FALSE(BaseProcessTest::handlerWasCalled());