diff options
Diffstat (limited to 'libs/assimp/code/AssetLib/MDL/HalfLife')
10 files changed, 0 insertions, 2895 deletions
diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1FileData.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1FileData.h deleted file mode 100644 index 28b1b28..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1FileData.h +++ /dev/null @@ -1,600 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1FileData.h - * @brief Definition of in-memory structures for the - * Half-Life 1 MDL file format. - */ - -#ifndef AI_HL1FILEDATA_INCLUDED -#define AI_HL1FILEDATA_INCLUDED - -#include "HalfLifeMDLBaseHeader.h" - -#include <assimp/Compiler/pushpack1.h> -#include <assimp/types.h> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -using vec3_t = float[3]; - -/** \struct Header_HL1 - * \brief Data structure for the HL1 MDL file header. - */ -struct Header_HL1 : HalfLifeMDLBaseHeader { - //! The model name. - char name[64]; - - //! The total file size in bytes. - int32_t length; - - //! Ideal eye position. - vec3_t eyeposition; - - //! Ideal movement hull size. - vec3_t min; - vec3_t max; - - //! Clipping bounding box. - vec3_t bbmin; - vec3_t bbmax; - - //! Was "flags". - int32_t unused; - - //! The number of bones. - int32_t numbones; - - //! Offset to the first bone chunk. - int32_t boneindex; - - //! The number of bone controllers. - int32_t numbonecontrollers; - - //! Offset to the first bone controller chunk. - int32_t bonecontrollerindex; - - //! The number of hitboxes. - int32_t numhitboxes; - - //! Offset to the first hitbox chunk. - int32_t hitboxindex; - - //! The number of sequences. - int32_t numseq; - - //! Offset to the first sequence description chunk. - int32_t seqindex; - - //! The number of sequence groups. - int32_t numseqgroups; - - //! Offset to the first sequence group chunk. - int32_t seqgroupindex; - - //! The number of textures. - int32_t numtextures; - - //! Offset to the first texture chunk. - int32_t textureindex; - - //! Offset to the first texture's image data. - int32_t texturedataindex; - - //! The number of replaceable textures. - int32_t numskinref; - - //! The number of skin families. - int32_t numskinfamilies; - - //! Offset to the first replaceable texture. - int32_t skinindex; - - //! The number of bodyparts. - int32_t numbodyparts; - - //! Offset the the first bodypart. - int32_t bodypartindex; - - //! The number of attachments. - int32_t numattachments; - - //! Offset the the first attachment chunk. - int32_t attachmentindex; - - //! Was "soundtable". - int32_t unused2; - - //! Was "soundindex". - int32_t unused3; - - //! Was "soundgroups". - int32_t unused4; - - //! Was "soundgroupindex". - int32_t unused5; - - //! The number of nodes in the sequence transition graph. - int32_t numtransitions; - - //! Offset the the first sequence transition. - int32_t transitionindex; -} PACK_STRUCT; - -/** \struct SequenceHeader_HL1 - * \brief Data structure for the file header of a demand loaded - * HL1 MDL sequence group file. - */ -struct SequenceHeader_HL1 : HalfLifeMDLBaseHeader { - //! The sequence group file name. - char name[64]; - - //! The total file size in bytes. - int32_t length; -} PACK_STRUCT; - -/** \struct Bone_HL1 - * \brief Data structure for a bone in HL1 MDL files. - */ -struct Bone_HL1 { - //! The bone name. - char name[32]; - - //! The parent bone index. (-1) If it has no parent. - int32_t parent; - - //! Was "flags". - int32_t unused; - - //! Available bone controller per motion type. - //! (-1) if no controller is available. - int32_t bonecontroller[6]; - - /*! Default position and rotation values where - * scale[0] = position.X - * scale[1] = position.Y - * scale[2] = position.Z - * scale[3] = rotation.X - * scale[4] = rotation.Y - * scale[5] = rotation.Z - */ - float value[6]; - - /*! Compressed scale values where - * scale[0] = position.X scale - * scale[1] = position.Y scale - * scale[2] = position.Z scale - * scale[3] = rotation.X scale - * scale[4] = rotation.Y scale - * scale[5] = rotation.Z scale - */ - float scale[6]; -} PACK_STRUCT; - -/** \struct BoneController_HL1 - * \brief Data structure for a bone controller in HL1 MDL files. - */ -struct BoneController_HL1 { - //! Bone affected by this controller. - int32_t bone; - - //! The motion type. - int32_t type; - - //! The minimum and maximum values. - float start; - float end; - - // Was "rest". - int32_t unused; - - // The bone controller channel. - int32_t index; -} PACK_STRUCT; - -/** \struct Hitbox_HL1 - * \brief Data structure for a hitbox in HL1 MDL files. - */ -struct Hitbox_HL1 { - //! The bone this hitbox follows. - int32_t bone; - - //! The hit group. - int32_t group; - - //! The hitbox minimum and maximum extents. - vec3_t bbmin; - vec3_t bbmax; -} PACK_STRUCT; - -/** \struct SequenceGroup_HL1 - * \brief Data structure for a sequence group in HL1 MDL files. - */ -struct SequenceGroup_HL1 { - //! A textual name for this sequence group. - char label[32]; - - //! The file name. - char name[64]; - - //! Was "cache". - int32_t unused; - - //! Was "data". - int32_t unused2; -} PACK_STRUCT; - -//! The type of blending for a sequence. -enum SequenceBlendMode_HL1 { - NoBlend = 1, - TwoWayBlending = 2, - FourWayBlending = 4, -}; - -/** \struct SequenceDesc_HL1 - * \brief Data structure for a sequence description in HL1 MDL files. - */ -struct SequenceDesc_HL1 { - //! The sequence name. - char label[32]; - - //! Frames per second. - float fps; - - //! looping/non-looping flags. - int32_t flags; - - //! The sequence activity. - int32_t activity; - - //! The sequence activity weight. - int32_t actweight; - - //! The number of animation events. - int32_t numevents; - - //! Offset the the first animation event chunk. - int32_t eventindex; - - //! The number of frames in the sequence. - int32_t numframes; - - //! Was "numpivots". - int32_t unused; - - //! Was "pivotindex". - int32_t unused2; - - //! Linear motion type. - int32_t motiontype; - - //! Linear motion bone. - int32_t motionbone; - - //! Linear motion. - vec3_t linearmovement; - - //! Was "automoveposindex". - int32_t unused3; - - //! Was "automoveangleindex". - int32_t unused4; - - //! The sequence minimum and maximum extents. - vec3_t bbmin; - vec3_t bbmax; - - //! The number of blend animations. - int32_t numblends; - - //! Offset to first the AnimValueOffset_HL1 chunk. - //! This offset is relative to the SequenceHeader_HL1 of the file - //! that contains the animation data. - int32_t animindex; - - //! The motion type of each blend controller. - int32_t blendtype[2]; - - //! The starting value of each blend controller. - float blendstart[2]; - - //! The ending value of each blend controller. - float blendend[2]; - - //! Was "blendparent". - int32_t unused5; - - //! The sequence group. - int32_t seqgroup; - - //! The node at entry in the sequence transition graph. - int32_t entrynode; - - //! The node at exit in the sequence transition graph. - int32_t exitnode; - - //! Transition rules. - int32_t nodeflags; - - //! Was "nextseq" - int32_t unused6; -} PACK_STRUCT; - -/** \struct AnimEvent_HL1 - * \brief Data structure for an animation event in HL1 MDL files. - */ -struct AnimEvent_HL1 { - //! The frame at which this animation event occurs. - int32_t frame; - - //! The script event type. - int32_t event; - - //! was "type" - int32_t unused; - - //! Options. Could be path to sound WAVE files. - char options[64]; -} PACK_STRUCT; - -/** \struct Attachment_HL1 - * \brief Data structure for an attachment in HL1 MDL files. - */ -struct Attachment_HL1 { - //! Was "name". - char unused[32]; - - //! Was "type". - int32_t unused2; - - //! The bone this attachment follows. - int32_t bone; - - //! The attachment origin. - vec3_t org; - - //! Was "vectors" - vec3_t unused3[3]; -} PACK_STRUCT; - -/** \struct AnimValueOffset_HL1 - * \brief Data structure to hold offsets (one per motion type) - * to the first animation frame value for a single bone - * in HL1 MDL files. - */ -struct AnimValueOffset_HL1 { - unsigned short offset[6]; -} PACK_STRUCT; - -/** \struct AnimValue_HL1 - * \brief Data structure for an animation frame in HL1 MDL files. - */ -union AnimValue_HL1 { - struct { - uint8_t valid; - uint8_t total; - } num; - short value; -} PACK_STRUCT; - -/** \struct Bodypart_HL1 - * \brief Data structure for a bodypart in HL1 MDL files. - */ -struct Bodypart_HL1 { - //! The bodypart name. - char name[64]; - - //! The number of available models for this bodypart. - int32_t nummodels; - - //! Used to convert from a global model index - //! to a local bodypart model index. - int32_t base; - - //! The offset to the first model chunk. - int32_t modelindex; -} PACK_STRUCT; - -/** \struct Texture_HL1 - * \brief Data structure for a texture in HL1 MDL files. - */ -struct Texture_HL1 { - //! Texture file name. - char name[64]; - - //! Texture flags. - int32_t flags; - - //! Texture width in pixels. - int32_t width; - - //! Texture height in pixels. - int32_t height; - - //! Offset to the image data. - //! This offset is relative to the texture file header. - int32_t index; -} PACK_STRUCT; - -/** \struct Model_HL1 - * \brief Data structure for a model in HL1 MDL files. - */ -struct Model_HL1 { - //! Model name. - char name[64]; - - //! Was "type". - int32_t unused; - - //! Was "boundingradius". - float unused2; - - //! The number of meshes in the model. - int32_t nummesh; - - //! Offset to the first mesh chunk. - int32_t meshindex; - - //! The number of unique vertices. - int32_t numverts; - - //! Offset to the vertex bone array. - int32_t vertinfoindex; - - //! Offset to the vertex array. - int32_t vertindex; - - //! The number of unique normals. - int32_t numnorms; - - //! Offset to the normal bone array. - int32_t norminfoindex; - - //! Offset to the normal array. - int32_t normindex; - - //! Was "numgroups". - int32_t unused3; - - //! Was "groupindex". - int32_t unused4; -} PACK_STRUCT; - -/** \struct Mesh_HL1 - * \brief Data structure for a mesh in HL1 MDL files. - */ -struct Mesh_HL1 { - //! Can be interpreted as the number of triangles in the mesh. - int32_t numtris; - - //! Offset to the start of the tris sequence. - int32_t triindex; - - //! The skin index. - int32_t skinref; - - //! The number of normals in the mesh. - int32_t numnorms; - - //! Was "normindex". - int32_t unused; -} PACK_STRUCT; - -/** \struct Trivert - * \brief Data structure for a trivert in HL1 MDL files. - */ -struct Trivert { - //! Index into Model_HL1 vertex array. - short vertindex; - - //! Index into Model_HL1 normal array. - short normindex; - - //! Texture coordinates in absolute space (unnormalized). - short s, t; -} PACK_STRUCT; - -#include <assimp/Compiler/poppack1.h> - -#if (!defined AI_MDL_HL1_VERSION) -#define AI_MDL_HL1_VERSION 10 -#endif -#if (!defined AI_MDL_HL1_MAX_TRIANGLES) -#define AI_MDL_HL1_MAX_TRIANGLES 20000 -#endif -#if (!defined AI_MDL_HL1_MAX_VERTICES) -#define AI_MDL_HL1_MAX_VERTICES 2048 -#endif -#if (!defined AI_MDL_HL1_MAX_SEQUENCES) -#define AI_MDL_HL1_MAX_SEQUENCES 2048 -#endif -#if (!defined AI_MDL_HL1_MAX_SEQUENCE_GROUPS) -#define AI_MDL_HL1_MAX_SEQUENCE_GROUPS 32 -#endif -#if (!defined AI_MDL_HL1_MAX_TEXTURES) -#define AI_MDL_HL1_MAX_TEXTURES 100 -#endif -#if (!defined AI_MDL_HL1_MAX_SKIN_FAMILIES) -#define AI_MDL_HL1_MAX_SKIN_FAMILIES 100 -#endif -#if (!defined AI_MDL_HL1_MAX_BONES) -#define AI_MDL_HL1_MAX_BONES 128 -#endif -#if (!defined AI_MDL_HL1_MAX_BODYPARTS) -#define AI_MDL_HL1_MAX_BODYPARTS 32 -#endif -#if (!defined AI_MDL_HL1_MAX_MODELS) -#define AI_MDL_HL1_MAX_MODELS 32 -#endif -#if (!defined AI_MDL_HL1_MAX_MESHES) -#define AI_MDL_HL1_MAX_MESHES 256 -#endif -#if (!defined AI_MDL_HL1_MAX_EVENTS) -#define AI_MDL_HL1_MAX_EVENTS 1024 -#endif -#if (!defined AI_MDL_HL1_MAX_BONE_CONTROLLERS) -#define AI_MDL_HL1_MAX_BONE_CONTROLLERS 8 -#endif -#if (!defined AI_MDL_HL1_MAX_ATTACHMENTS) -#define AI_MDL_HL1_MAX_ATTACHMENTS 512 -#endif - -// lighting options -#if (!defined AI_MDL_HL1_STUDIO_NF_FLATSHADE) -#define AI_MDL_HL1_STUDIO_NF_FLATSHADE 0x0001 -#endif -#if (!defined AI_MDL_HL1_STUDIO_NF_CHROME) -#define AI_MDL_HL1_STUDIO_NF_CHROME 0x0002 -#endif -#if (!defined AI_MDL_HL1_STUDIO_NF_ADDITIVE) -#define AI_MDL_HL1_STUDIO_NF_ADDITIVE 0x0020 -#endif -#if (!defined AI_MDL_HL1_STUDIO_NF_MASKED) -#define AI_MDL_HL1_STUDIO_NF_MASKED 0x0040 -#endif - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_HL1FILEDATA_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h deleted file mode 100644 index d412aee..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1ImportDefinitions.h - * @brief HL1 MDL loader specific definitions. - */ - -#ifndef AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED -#define AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED - -#define AI_MDL_HL1_NODE_ROOT "<MDL_root>" -#define AI_MDL_HL1_NODE_BODYPARTS "<MDL_bodyparts>" -#define AI_MDL_HL1_NODE_BONES "<MDL_bones>" -#define AI_MDL_HL1_NODE_BONE_CONTROLLERS "<MDL_bone_controllers>" -#define AI_MDL_HL1_NODE_SEQUENCE_INFOS "<MDL_sequence_infos>" -#define AI_MDL_HL1_NODE_SEQUENCE_GROUPS "<MDL_sequence_groups>" -#define AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH "<MDL_sequence_transition_graph>" -#define AI_MDL_HL1_NODE_ATTACHMENTS "<MDL_attachments>" -#define AI_MDL_HL1_NODE_HITBOXES "<MDL_hitboxes>" -#define AI_MDL_HL1_NODE_GLOBAL_INFO "<MDL_global_info>" -#define AI_MDL_HL1_NODE_ANIMATION_EVENTS "AnimationEvents" -#define AI_MDL_HL1_NODE_BLEND_CONTROLLERS "BlendControllers" - -#define AI_MDL_HL1_MATKEY_CHROME(type, N) "$mat.HL1.chrome", type, N - -#endif // AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h deleted file mode 100644 index 340ba2d..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h +++ /dev/null @@ -1,85 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1ImportSettings.h - * @brief Half-Life 1 MDL loader configuration settings. - */ - -#ifndef AI_HL1IMPORTSETTINGS_INCLUDED -#define AI_HL1IMPORTSETTINGS_INCLUDED - -#include <string> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -struct HL1ImportSettings { - HL1ImportSettings() : - read_animations(false), - read_animation_events(false), - read_blend_controllers(false), - read_sequence_groups_info(false), - read_sequence_transitions(false), - read_attachments(false), - read_bone_controllers(false), - read_hitboxes(false), - read_textures(false), - read_misc_global_info(false) { - } - - bool read_animations; - bool read_animation_events; - bool read_blend_controllers; - bool read_sequence_groups_info; - bool read_sequence_transitions; - bool read_attachments; - bool read_bone_controllers; - bool read_hitboxes; - bool read_textures; - bool read_misc_global_info; -}; - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_HL1IMPORTSETTINGS_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp deleted file mode 100644 index 93d3753..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp +++ /dev/null @@ -1,1353 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1MDLLoader.cpp - * @brief Implementation for the Half-Life 1 MDL loader. - */ - -#include "HL1MDLLoader.h" -#include "HL1ImportDefinitions.h" -#include "HL1MeshTrivert.h" -#include "UniqueNameGenerator.h" - -#include <assimp/BaseImporter.h> -#include <assimp/StringUtils.h> -#include <assimp/ai_assert.h> -#include <assimp/qnan.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/Importer.hpp> - -#include <iomanip> -#include <sstream> -#include <map> - -#ifdef MDL_HALFLIFE_LOG_WARN_HEADER -#undef MDL_HALFLIFE_LOG_WARN_HEADER -#endif -#define MDL_HALFLIFE_LOG_HEADER "[Half-Life 1 MDL] " -#include "LogFunctions.h" - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -#ifdef _MSC_VER -# pragma warning(disable : 4706) -#endif // _MSC_VER - -// ------------------------------------------------------------------------------------------------ -HL1MDLLoader::HL1MDLLoader( - aiScene *scene, - IOSystem *io, - const unsigned char *buffer, - const std::string &file_path, - const HL1ImportSettings &import_settings) : - scene_(scene), - io_(io), - buffer_(buffer), - file_path_(file_path), - import_settings_(import_settings), - header_(nullptr), - texture_header_(nullptr), - anim_headers_(nullptr), - texture_buffer_(nullptr), - anim_buffers_(nullptr), - num_sequence_groups_(0), - rootnode_children_(), - unique_name_generator_(), - unique_sequence_names_(), - unique_sequence_groups_names_(), - temp_bones_(), - num_blend_controllers_(0), - total_models_(0) { - load_file(); -} - -// ------------------------------------------------------------------------------------------------ -HL1MDLLoader::~HL1MDLLoader() { - release_resources(); -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::release_resources() { - if (buffer_ != texture_buffer_) { - delete[] texture_buffer_; - texture_buffer_ = nullptr; - } - - if (num_sequence_groups_ && anim_buffers_) { - for (int i = 1; i < num_sequence_groups_; ++i) { - if (anim_buffers_[i]) { - delete[] anim_buffers_[i]; - anim_buffers_[i] = nullptr; - } - } - - delete[] anim_buffers_; - anim_buffers_ = nullptr; - } - - if (anim_headers_) { - delete[] anim_headers_; - anim_headers_ = nullptr; - } - - // Root has some children nodes. so let's proceed them - if (!rootnode_children_.empty()) { - // Here, it means that the nodes were not added to the - // scene root node. We still have to delete them. - for (auto it = rootnode_children_.begin(); it != rootnode_children_.end(); ++it) { - if (*it) { - delete *it; - } - } - // Ensure this happens only once. - rootnode_children_.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::load_file() { - try { - header_ = (const Header_HL1 *)buffer_; - validate_header(header_, false); - - // Create the root scene node. - scene_->mRootNode = new aiNode(AI_MDL_HL1_NODE_ROOT); - - load_texture_file(); - - if (import_settings_.read_animations) { - load_sequence_groups_files(); - } - - read_textures(); - read_skins(); - - read_bones(); - read_meshes(); - - if (import_settings_.read_animations) { - read_sequence_groups_info(); - read_animations(); - read_sequence_infos(); - if (import_settings_.read_sequence_transitions) - read_sequence_transitions(); - } - - if (import_settings_.read_attachments) { - read_attachments(); - } - - if (import_settings_.read_hitboxes) { - read_hitboxes(); - } - - if (import_settings_.read_bone_controllers) { - read_bone_controllers(); - } - - read_global_info(); - - if (!header_->numbodyparts) { - // This could be an MDL external texture file. In this case, - // add this flag to allow the scene to be loaded even if it - // has no meshes. - scene_->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - // Append children to root node. - if (rootnode_children_.size()) { - scene_->mRootNode->addChildren( - static_cast<unsigned int>(rootnode_children_.size()), - rootnode_children_.data()); - - // Clear the list of nodes so they will not be destroyed - // when resources are released. - rootnode_children_.clear(); - } - - release_resources(); - - } catch (...) { - release_resources(); - throw; - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::validate_header(const Header_HL1 *header, bool is_texture_header) { - if (is_texture_header) { - // Every single Half-Life model is assumed to have at least one texture. - if (!header->numtextures) { - throw DeadlyImportError(MDL_HALFLIFE_LOG_HEADER "There are no textures in the file"); - } - - if (header->numtextures > AI_MDL_HL1_MAX_TEXTURES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_TEXTURES>(header->numtextures, "textures"); - } - - if (header->numskinfamilies > AI_MDL_HL1_MAX_SKIN_FAMILIES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_SKIN_FAMILIES>(header->numskinfamilies, "skin families"); - } - - } else { - - if (header->numbodyparts > AI_MDL_HL1_MAX_BODYPARTS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_BODYPARTS>(header->numbodyparts, "bodyparts"); - } - - if (header->numbones > AI_MDL_HL1_MAX_BONES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_BONES>(header->numbones, "bones"); - } - - if (header->numbonecontrollers > AI_MDL_HL1_MAX_BONE_CONTROLLERS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_BONE_CONTROLLERS>(header->numbonecontrollers, "bone controllers"); - } - - if (header->numseq > AI_MDL_HL1_MAX_SEQUENCES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_SEQUENCES>(header->numseq, "sequences"); - } - - if (header->numseqgroups > AI_MDL_HL1_MAX_SEQUENCE_GROUPS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_SEQUENCE_GROUPS>(header->numseqgroups, "sequence groups"); - } - - if (header->numattachments > AI_MDL_HL1_MAX_ATTACHMENTS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_ATTACHMENTS>(header->numattachments, "attachments"); - } - } -} - -// ------------------------------------------------------------------------------------------------ -/* - Load textures. - - There are two ways for textures to be stored in a Half-Life model: - - 1. Directly in the MDL file (filePath) or - 2. In an external MDL file. - - Due to the way StudioMDL works (tool used to compile SMDs into MDLs), - it is assumed that an external texture file follows the naming - convention: <YourModelName>T.mdl. Note the extra (T) at the end of the - model name. - - .e.g For a given model named MyModel.mdl - - The external texture file name would be MyModelT.mdl -*/ -void HL1MDLLoader::load_texture_file() { - if (header_->numtextures == 0) { - // Load an external MDL texture file. - std::string texture_file_path = - DefaultIOSystem::absolutePath(file_path_) + io_->getOsSeparator() + - DefaultIOSystem::completeBaseName(file_path_) + "T." + - BaseImporter::GetExtension(file_path_); - - load_file_into_buffer<Header_HL1>(texture_file_path, texture_buffer_); - } else { - // Model has no external texture file. This means the texture is stored inside the main MDL file. - texture_buffer_ = const_cast<unsigned char *>(buffer_); - } - - texture_header_ = (const Header_HL1 *)texture_buffer_; - - // Validate texture header. - validate_header(texture_header_, true); -} - -// ------------------------------------------------------------------------------------------------ -/* - Load sequence group files if any. - - Due to the way StudioMDL works (tool used to compile SMDs into MDLs), - it is assumed that a sequence group file follows the naming - convention: <YourModelName>0X.mdl. Note the extra (0X) at the end of - the model name, where (X) is the sequence group. - - .e.g For a given model named MyModel.mdl - - Sequence group 1 => MyModel01.mdl - Sequence group 2 => MyModel02.mdl - Sequence group X => MyModel0X.mdl - -*/ -void HL1MDLLoader::load_sequence_groups_files() { - if (header_->numseqgroups <= 1) { - return; - } - - num_sequence_groups_ = header_->numseqgroups; - - anim_buffers_ = new unsigned char *[num_sequence_groups_]; - anim_headers_ = new SequenceHeader_HL1 *[num_sequence_groups_]; - for (int i = 0; i < num_sequence_groups_; ++i) { - anim_buffers_[i] = nullptr; - anim_headers_[i] = nullptr; - } - - std::string file_path_without_extension = - DefaultIOSystem::absolutePath(file_path_) + - io_->getOsSeparator() + - DefaultIOSystem::completeBaseName(file_path_); - - for (int i = 1; i < num_sequence_groups_; ++i) { - std::stringstream ss; - ss << file_path_without_extension; - ss << std::setw(2) << std::setfill('0') << i; - ss << '.' << BaseImporter::GetExtension(file_path_); - - std::string sequence_file_path = ss.str(); - - load_file_into_buffer<SequenceHeader_HL1>(sequence_file_path, anim_buffers_[i]); - - anim_headers_[i] = (SequenceHeader_HL1 *)anim_buffers_[i]; - } -} - -// ------------------------------------------------------------------------------------------------ -// Read an MDL texture. -void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture, - uint8_t *data, uint8_t *pal, aiTexture *pResult, - aiColor3D &last_palette_color) { - pResult->mFilename = ptexture->name; - pResult->mWidth = static_cast<unsigned int>(ptexture->width); - pResult->mHeight = static_cast<unsigned int>(ptexture->height); - pResult->achFormatHint[0] = 'r'; - pResult->achFormatHint[1] = 'g'; - pResult->achFormatHint[2] = 'b'; - pResult->achFormatHint[3] = 'a'; - pResult->achFormatHint[4] = '8'; - pResult->achFormatHint[5] = '8'; - pResult->achFormatHint[6] = '8'; - pResult->achFormatHint[7] = '8'; - pResult->achFormatHint[8] = '\0'; - - const size_t num_pixels = pResult->mWidth * pResult->mHeight; - aiTexel *out = pResult->pcData = new aiTexel[num_pixels]; - - // Convert indexed 8 bit to 32 bit RGBA. - for (size_t i = 0; i < num_pixels; ++i, ++out) { - out->r = pal[data[i] * 3]; - out->g = pal[data[i] * 3 + 1]; - out->b = pal[data[i] * 3 + 2]; - out->a = 255; - } - - // Get the last palette color. - last_palette_color.r = pal[255 * 3]; - last_palette_color.g = pal[255 * 3 + 1]; - last_palette_color.b = pal[255 * 3 + 2]; -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_textures() { - const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex); - unsigned char *pin = texture_buffer_; - - scene_->mNumTextures = scene_->mNumMaterials = texture_header_->numtextures; - scene_->mTextures = new aiTexture *[scene_->mNumTextures]; - scene_->mMaterials = new aiMaterial *[scene_->mNumMaterials]; - - for (int i = 0; i < texture_header_->numtextures; ++i) { - scene_->mTextures[i] = new aiTexture(); - - aiColor3D last_palette_color; - read_texture(&ptexture[i], - pin + ptexture[i].index, - pin + ptexture[i].width * ptexture[i].height + ptexture[i].index, - scene_->mTextures[i], - last_palette_color); - - aiMaterial *scene_material = scene_->mMaterials[i] = new aiMaterial(); - - const aiTextureType texture_type = aiTextureType_DIFFUSE; - aiString texture_name(ptexture[i].name); - scene_material->AddProperty(&texture_name, AI_MATKEY_TEXTURE(texture_type, 0)); - - // Is this a chrome texture? - int chrome = ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_CHROME ? 1 : 0; - scene_material->AddProperty(&chrome, 1, AI_MDL_HL1_MATKEY_CHROME(texture_type, 0)); - - if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_FLATSHADE) { - // Flat shading. - const aiShadingMode shading_mode = aiShadingMode_Flat; - scene_material->AddProperty(&shading_mode, 1, AI_MATKEY_SHADING_MODEL); - } - - if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_ADDITIVE) { - // Additive texture. - const aiBlendMode blend_mode = aiBlendMode_Additive; - scene_material->AddProperty(&blend_mode, 1, AI_MATKEY_BLEND_FUNC); - } else if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_MASKED) { - // Texture with 1 bit alpha test. - const aiTextureFlags use_alpha = aiTextureFlags_UseAlpha; - scene_material->AddProperty(&use_alpha, 1, AI_MATKEY_TEXFLAGS(texture_type, 0)); - scene_material->AddProperty(&last_palette_color, 1, AI_MATKEY_COLOR_TRANSPARENT); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_skins() { - // Read skins, if any. - if (texture_header_->numskinfamilies <= 1) { - return; - } - - // Pointer to base texture index. - short *default_skin_ptr = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex); - - // Start at first replacement skin. - short *replacement_skin_ptr = default_skin_ptr + texture_header_->numskinref; - - for (int i = 1; i < texture_header_->numskinfamilies; ++i, replacement_skin_ptr += texture_header_->numskinref) { - for (int j = 0; j < texture_header_->numskinref; ++j) { - if (default_skin_ptr[j] != replacement_skin_ptr[j]) { - // Save replacement textures. - aiString skinMaterialId(scene_->mTextures[replacement_skin_ptr[j]]->mFilename); - scene_->mMaterials[default_skin_ptr[j]]->AddProperty(&skinMaterialId, AI_MATKEY_TEXTURE_DIFFUSE(i)); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_bones() { - if (!header_->numbones) { - return; - } - - const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex); - - std::vector<std::string> unique_bones_names(header_->numbones); - for (int i = 0; i < header_->numbones; ++i) { - unique_bones_names[i] = pbone[i].name; - } - - // Ensure bones have unique names. - unique_name_generator_.set_template_name("Bone"); - unique_name_generator_.make_unique(unique_bones_names); - - temp_bones_.resize(header_->numbones); - - aiNode *bones_node = new aiNode(AI_MDL_HL1_NODE_BONES); - rootnode_children_.push_back(bones_node); - bones_node->mNumChildren = static_cast<unsigned int>(header_->numbones); - bones_node->mChildren = new aiNode *[bones_node->mNumChildren]; - - // Create bone matrices in local space. - for (int i = 0; i < header_->numbones; ++i) { - aiNode *bone_node = temp_bones_[i].node = bones_node->mChildren[i] = new aiNode(unique_bones_names[i]); - - aiVector3D angles(pbone[i].value[3], pbone[i].value[4], pbone[i].value[5]); - temp_bones_[i].absolute_transform = bone_node->mTransformation = - aiMatrix4x4(aiVector3D(1), aiQuaternion(angles.y, angles.z, angles.x), - aiVector3D(pbone[i].value[0], pbone[i].value[1], pbone[i].value[2])); - - if (pbone[i].parent == -1) { - bone_node->mParent = scene_->mRootNode; - } else { - bone_node->mParent = bones_node->mChildren[pbone[i].parent]; - - temp_bones_[i].absolute_transform = - temp_bones_[pbone[i].parent].absolute_transform * bone_node->mTransformation; - } - - temp_bones_[i].offset_matrix = temp_bones_[i].absolute_transform; - temp_bones_[i].offset_matrix.Inverse(); - } -} - -// ------------------------------------------------------------------------------------------------ -/* - Read meshes. - - Half-Life MDLs are structured such that each MDL - contains one or more 'bodypart(s)', which contain one - or more 'model(s)', which contains one or more mesh(es). - - * Bodyparts are used to group models that may be replaced - in the game .e.g a character could have a 'heads' group, - 'torso' group, 'shoes' group, with each group containing - different 'model(s)'. - - * Models, also called 'sub models', contain vertices as - well as a reference to each mesh used by the sub model. - - * Meshes contain a list of tris, also known as 'triverts'. - Each tris contains the following information: - - 1. The index of the position to use for the vertex. - 2. The index of the normal to use for the vertex. - 3. The S coordinate to use for the vertex UV. - 4. The T coordinate ^ - - These tris represent the way to represent the triangles - for each mesh. Depending on how the tool compiled the MDL, - those triangles were saved as strips and or fans. - - NOTE: Each tris is NOT unique. This means that you - might encounter the same vertex index but with a different - normal index, S coordinate, T coordinate. - - In addition, each mesh contains the texture's index. - - ------------------------------------------------------ - With the details above, there are several things to - take into consideration. - - * The Half-Life models store the vertices by sub model - rather than by mesh. Due to Assimp's structure, it - is necessary to remap each model vertex to be used - per mesh. Unfortunately, this has the consequence - to duplicate vertices. - - * Because the mesh triangles are comprised of strips and - fans, it is necessary to convert each primitive to - triangles, respectively (3 indices per face). -*/ -void HL1MDLLoader::read_meshes() { - if (!header_->numbodyparts) { - return; - } - - int total_verts = 0; - int total_triangles = 0; - total_models_ = 0; - - const Bodypart_HL1 *pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); - const Model_HL1 *pmodel = nullptr; - const Mesh_HL1 *pmesh = nullptr; - - const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex); - short *pskinref = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex); - - scene_->mNumMeshes = 0; - - std::vector<std::string> unique_bodyparts_names; - unique_bodyparts_names.resize(header_->numbodyparts); - - // Count the number of meshes. - - for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) { - unique_bodyparts_names[i] = pbodypart->name; - - pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); - for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel) { - scene_->mNumMeshes += pmodel->nummesh; - total_verts += pmodel->numverts; - } - - total_models_ += pbodypart->nummodels; - } - - // Display limit infos. - if (total_verts > AI_MDL_HL1_MAX_VERTICES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_VERTICES>(total_verts, "vertices"); - } - - if (scene_->mNumMeshes > AI_MDL_HL1_MAX_MESHES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_MESHES>(scene_->mNumMeshes, "meshes"); - } - - if (total_models_ > AI_MDL_HL1_MAX_MODELS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_MODELS>(total_models_, "models"); - } - - // Ensure bodyparts have unique names. - unique_name_generator_.set_template_name("Bodypart"); - unique_name_generator_.make_unique(unique_bodyparts_names); - - // Now do the same for each model. - pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); - - // Prepare template name for bodypart models. - std::vector<std::string> unique_models_names; - unique_models_names.resize(total_models_); - - unsigned int model_index = 0; - - for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) { - pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); - for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel, ++model_index) - unique_models_names[model_index] = pmodel->name; - } - - unique_name_generator_.set_template_name("Model"); - unique_name_generator_.make_unique(unique_models_names); - - unsigned int mesh_index = 0; - - scene_->mMeshes = new aiMesh *[scene_->mNumMeshes]; - - pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); - - /* Create a node that will represent the mesh hierarchy. - - <MDL_bodyparts> - | - +-- bodypart --+-- model -- [mesh index, mesh index, ...] - | | - | +-- model -- [mesh index, mesh index, ...] - | | - | ... - | - |-- bodypart -- ... - | - ... - */ - aiNode *bodyparts_node = new aiNode(AI_MDL_HL1_NODE_BODYPARTS); - rootnode_children_.push_back(bodyparts_node); - bodyparts_node->mNumChildren = static_cast<unsigned int>(header_->numbodyparts); - bodyparts_node->mChildren = new aiNode *[bodyparts_node->mNumChildren]; - aiNode **bodyparts_node_ptr = bodyparts_node->mChildren; - - // The following variables are defined here so they don't have - // to be recreated every iteration. - - // Model_HL1 vertices, in bind pose space. - std::vector<aiVector3D> bind_pose_vertices; - - // Model_HL1 normals, in bind pose space. - std::vector<aiVector3D> bind_pose_normals; - - // Used to contain temporary information for building a mesh. - std::vector<HL1MeshTrivert> triverts; - - std::vector<short> tricmds; - - // Which triverts to use for the mesh. - std::vector<short> mesh_triverts_indices; - - std::vector<HL1MeshFace> mesh_faces; - - /* triverts that have the same vertindex, but have different normindex,s,t values. - Similar triverts are mapped from vertindex to a list of similar triverts. */ - std::map<short, std::set<short>> triverts_similars; - - // triverts per bone. - std::map<int, std::set<short>> bone_triverts; - - /** This function adds a trivert index to the list of triverts per bone. - * \param[in] bone The bone that affects the trivert at index \p trivert_index. - * \param[in] trivert_index The trivert index. - */ - auto AddTrivertToBone = [&](int bone, short trivert_index) { - if (bone_triverts.count(bone) == 0) - bone_triverts.insert({ bone, std::set<short>{ trivert_index }}); - else - bone_triverts[bone].insert(trivert_index); - }; - - /** This function creates and appends a new trivert to the list of triverts. - * \param[in] trivert The trivert to use as a prototype. - * \param[in] bone The bone that affects \p trivert. - */ - auto AddSimilarTrivert = [&](const Trivert &trivert, const int bone) { - HL1MeshTrivert new_trivert(trivert); - new_trivert.localindex = static_cast<short>(mesh_triverts_indices.size()); - - short new_trivert_index = static_cast<short>(triverts.size()); - - if (triverts_similars.count(trivert.vertindex) == 0) - triverts_similars.insert({ trivert.vertindex, std::set<short>{ new_trivert_index }}); - else - triverts_similars[trivert.vertindex].insert(new_trivert_index); - - triverts.push_back(new_trivert); - - mesh_triverts_indices.push_back(new_trivert_index); - tricmds.push_back(new_trivert.localindex); - AddTrivertToBone(bone, new_trivert.localindex); - }; - - model_index = 0; - - for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart, ++bodyparts_node_ptr) { - pmodel = (const Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); - - // Create bodypart node for the mesh tree hierarchy. - aiNode *bodypart_node = (*bodyparts_node_ptr) = new aiNode(unique_bodyparts_names[i]); - bodypart_node->mParent = bodyparts_node; - bodypart_node->mMetaData = aiMetadata::Alloc(1); - bodypart_node->mMetaData->Set(0, "Base", pbodypart->base); - - bodypart_node->mNumChildren = static_cast<unsigned int>(pbodypart->nummodels); - bodypart_node->mChildren = new aiNode *[bodypart_node->mNumChildren]; - aiNode **bodypart_models_ptr = bodypart_node->mChildren; - - for (int j = 0; j < pbodypart->nummodels; - ++j, ++pmodel, ++bodypart_models_ptr, ++model_index) { - - pmesh = (const Mesh_HL1 *)((uint8_t *)header_ + pmodel->meshindex); - - uint8_t *pvertbone = ((uint8_t *)header_ + pmodel->vertinfoindex); - uint8_t *pnormbone = ((uint8_t *)header_ + pmodel->norminfoindex); - vec3_t *pstudioverts = (vec3_t *)((uint8_t *)header_ + pmodel->vertindex); - vec3_t *pstudionorms = (vec3_t *)((uint8_t *)header_ + pmodel->normindex); - - // Each vertex and normal is in local space, so transform - // each of them to bring them in bind pose. - bind_pose_vertices.resize(pmodel->numverts); - bind_pose_normals.resize(pmodel->numnorms); - for (size_t k = 0; k < bind_pose_vertices.size(); ++k) { - const vec3_t &vert = pstudioverts[k]; - bind_pose_vertices[k] = temp_bones_[pvertbone[k]].absolute_transform * aiVector3D(vert[0], vert[1], vert[2]); - } - for (size_t k = 0; k < bind_pose_normals.size(); ++k) { - const vec3_t &norm = pstudionorms[k]; - // Compute the normal matrix to transform the normal into bind pose, - // without affecting its length. - const aiMatrix4x4 normal_matrix = aiMatrix4x4(temp_bones_[pnormbone[k]].absolute_transform).Inverse().Transpose(); - bind_pose_normals[k] = normal_matrix * aiVector3D(norm[0], norm[1], norm[2]); - } - - // Create model node for the mesh tree hierarchy. - aiNode *model_node = (*bodypart_models_ptr) = new aiNode(unique_models_names[model_index]); - model_node->mParent = bodypart_node; - model_node->mNumMeshes = static_cast<unsigned int>(pmodel->nummesh); - model_node->mMeshes = new unsigned int[model_node->mNumMeshes]; - unsigned int *model_meshes_ptr = model_node->mMeshes; - - for (int k = 0; k < pmodel->nummesh; ++k, ++pmesh, ++mesh_index, ++model_meshes_ptr) { - *model_meshes_ptr = mesh_index; - - // Read triverts. - short *ptricmds = (short *)((uint8_t *)header_ + pmesh->triindex); - float texcoords_s_scale = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width; - float texcoords_t_scale = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height; - - // Reset the data for the upcoming mesh. - triverts.clear(); - triverts.resize(pmodel->numverts); - mesh_triverts_indices.clear(); - mesh_faces.clear(); - triverts_similars.clear(); - bone_triverts.clear(); - - int l; - while ((l = *(ptricmds++))) { - bool is_triangle_fan = false; - - if (l < 0) { - l = -l; - is_triangle_fan = true; - } - - // Clear the list of tris for the upcoming tris. - tricmds.clear(); - - for (; l > 0; l--, ptricmds += 4) { - const Trivert *input_trivert = reinterpret_cast<const Trivert *>(ptricmds); - const int bone = pvertbone[input_trivert->vertindex]; - - HL1MeshTrivert *private_trivert = &triverts[input_trivert->vertindex]; - if (private_trivert->localindex == -1) { - // First time referenced. - *private_trivert = *input_trivert; - private_trivert->localindex = static_cast<short>(mesh_triverts_indices.size()); - mesh_triverts_indices.push_back(input_trivert->vertindex); - tricmds.push_back(private_trivert->localindex); - AddTrivertToBone(bone, private_trivert->localindex); - } else if (*private_trivert == *input_trivert) { - // Exists and is the same. - tricmds.push_back(private_trivert->localindex); - } else { - // No similar trivert associated to the trivert currently processed. - if (triverts_similars.count(input_trivert->vertindex) == 0) - AddSimilarTrivert(*input_trivert, bone); - else { - // Search in the list of similar triverts to see if the - // trivert in process is already registered. - short similar_index = -1; - for (auto it = triverts_similars[input_trivert->vertindex].cbegin(); - similar_index == -1 && it != triverts_similars[input_trivert->vertindex].cend(); - ++it) { - if (triverts[*it] == *input_trivert) - similar_index = *it; - } - - // If a similar trivert has been found, reuse it. - // Otherwise, add it. - if (similar_index == -1) - AddSimilarTrivert(*input_trivert, bone); - else - tricmds.push_back(triverts[similar_index].localindex); - } - } - } - - // Build mesh faces. - const int num_faces = static_cast<int>(tricmds.size() - 2); - mesh_faces.reserve(num_faces); - - if (is_triangle_fan) { - for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { - mesh_faces.push_back(HL1MeshFace{ - tricmds[0], - tricmds[faceIdx + 1], - tricmds[faceIdx + 2] }); - } - } else { - for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { - if (faceIdx & 1) { - // Preserve winding order. - mesh_faces.push_back(HL1MeshFace{ - tricmds[faceIdx + 1], - tricmds[faceIdx], - tricmds[faceIdx + 2] }); - } else { - mesh_faces.push_back(HL1MeshFace{ - tricmds[faceIdx], - tricmds[faceIdx + 1], - tricmds[faceIdx + 2] }); - } - } - } - - total_triangles += num_faces; - } - - // Create the scene mesh. - aiMesh *scene_mesh = scene_->mMeshes[mesh_index] = new aiMesh(); - scene_mesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_TRIANGLE; - scene_mesh->mMaterialIndex = pskinref[pmesh->skinref]; - - scene_mesh->mNumVertices = static_cast<unsigned int>(mesh_triverts_indices.size()); - - if (scene_mesh->mNumVertices) { - scene_mesh->mVertices = new aiVector3D[scene_mesh->mNumVertices]; - scene_mesh->mNormals = new aiVector3D[scene_mesh->mNumVertices]; - - scene_mesh->mNumUVComponents[0] = 2; - scene_mesh->mTextureCoords[0] = new aiVector3D[scene_mesh->mNumVertices]; - - // Add vertices. - for (unsigned int v = 0; v < scene_mesh->mNumVertices; ++v) { - const HL1MeshTrivert *pTrivert = &triverts[mesh_triverts_indices[v]]; - scene_mesh->mVertices[v] = bind_pose_vertices[pTrivert->vertindex]; - scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex]; - scene_mesh->mTextureCoords[0][v] = aiVector3D( - pTrivert->s * texcoords_s_scale, - pTrivert->t * -texcoords_t_scale, 0); - } - - // Add face and indices. - scene_mesh->mNumFaces = static_cast<unsigned int>(mesh_faces.size()); - scene_mesh->mFaces = new aiFace[scene_mesh->mNumFaces]; - - for (unsigned int f = 0; f < scene_mesh->mNumFaces; ++f) { - aiFace *face = &scene_mesh->mFaces[f]; - face->mNumIndices = 3; - face->mIndices = new unsigned int[3]; - face->mIndices[0] = mesh_faces[f].v2; - face->mIndices[1] = mesh_faces[f].v1; - face->mIndices[2] = mesh_faces[f].v0; - } - - // Add mesh bones. - scene_mesh->mNumBones = static_cast<unsigned int>(bone_triverts.size()); - scene_mesh->mBones = new aiBone *[scene_mesh->mNumBones]; - - aiBone **scene_bone_ptr = scene_mesh->mBones; - - for (auto bone_it = bone_triverts.cbegin(); - bone_it != bone_triverts.cend(); - ++bone_it, ++scene_bone_ptr) { - const int bone_index = bone_it->first; - - aiBone *scene_bone = (*scene_bone_ptr) = new aiBone(); - scene_bone->mName = temp_bones_[bone_index].node->mName; - - scene_bone->mOffsetMatrix = temp_bones_[bone_index].offset_matrix; - - auto vertex_ids = bone_triverts.at(bone_index); - - // Add vertex weight per bone. - scene_bone->mNumWeights = static_cast<unsigned int>(vertex_ids.size()); - aiVertexWeight *vertex_weight_ptr = scene_bone->mWeights = new aiVertexWeight[scene_bone->mNumWeights]; - - for (auto vertex_it = vertex_ids.begin(); - vertex_it != vertex_ids.end(); - ++vertex_it, ++vertex_weight_ptr) { - vertex_weight_ptr->mVertexId = *vertex_it; - vertex_weight_ptr->mWeight = 1.0f; - } - } - } - } - } - } - - if (total_triangles > AI_MDL_HL1_MAX_TRIANGLES) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_TRIANGLES>(total_triangles, "triangles"); - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_animations() { - if (!header_->numseq) { - return; - } - - const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); - const SequenceGroup_HL1 *pseqgroup = nullptr; - const AnimValueOffset_HL1 *panim = nullptr; - const AnimValue_HL1 *panimvalue = nullptr; - - unique_sequence_names_.resize(header_->numseq); - for (int i = 0; i < header_->numseq; ++i) - unique_sequence_names_[i] = pseqdesc[i].label; - - // Ensure sequences have unique names. - unique_name_generator_.set_template_name("Sequence"); - unique_name_generator_.make_unique(unique_sequence_names_); - - scene_->mNumAnimations = 0; - - int highest_num_blend_animations = SequenceBlendMode_HL1::NoBlend; - - // Count the total number of animations. - for (int i = 0; i < header_->numseq; ++i, ++pseqdesc) { - scene_->mNumAnimations += pseqdesc->numblends; - highest_num_blend_animations = std::max(pseqdesc->numblends, highest_num_blend_animations); - } - - // Get the number of available blend controllers for global info. - get_num_blend_controllers(highest_num_blend_animations, num_blend_controllers_); - - pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); - - aiAnimation **scene_animations_ptr = scene_->mAnimations = new aiAnimation *[scene_->mNumAnimations]; - - for (int sequence = 0; sequence < header_->numseq; ++sequence, ++pseqdesc) { - pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex) + pseqdesc->seqgroup; - - if (pseqdesc->seqgroup == 0) { - panim = (const AnimValueOffset_HL1 *)((uint8_t *)header_ + pseqgroup->unused2 + pseqdesc->animindex); - } else { - panim = (const AnimValueOffset_HL1 *)((uint8_t *)anim_headers_[pseqdesc->seqgroup] + pseqdesc->animindex); - } - - for (int blend = 0; blend < pseqdesc->numblends; ++blend, ++scene_animations_ptr) { - - const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex); - - aiAnimation *scene_animation = (*scene_animations_ptr) = new aiAnimation(); - - scene_animation->mName = unique_sequence_names_[sequence]; - scene_animation->mTicksPerSecond = pseqdesc->fps; - scene_animation->mDuration = static_cast<double>(pseqdesc->fps) * pseqdesc->numframes; - scene_animation->mNumChannels = static_cast<unsigned int>(header_->numbones); - scene_animation->mChannels = new aiNodeAnim *[scene_animation->mNumChannels]; - - for (int bone = 0; bone < header_->numbones; bone++, ++pbone, ++panim) { - aiNodeAnim *node_anim = scene_animation->mChannels[bone] = new aiNodeAnim(); - node_anim->mNodeName = temp_bones_[bone].node->mName; - - node_anim->mNumPositionKeys = pseqdesc->numframes; - node_anim->mNumRotationKeys = node_anim->mNumPositionKeys; - node_anim->mNumScalingKeys = 0; - - node_anim->mPositionKeys = new aiVectorKey[node_anim->mNumPositionKeys]; - node_anim->mRotationKeys = new aiQuatKey[node_anim->mNumRotationKeys]; - - for (int frame = 0; frame < pseqdesc->numframes; ++frame) { - aiVectorKey *position_key = &node_anim->mPositionKeys[frame]; - aiQuatKey *rotation_key = &node_anim->mRotationKeys[frame]; - - aiVector3D angle1; - for (int j = 0; j < 3; ++j) { - if (panim->offset[j + 3] != 0) { - // Read compressed rotation delta. - panimvalue = (const AnimValue_HL1 *)((uint8_t *)panim + panim->offset[j + 3]); - extract_anim_value(panimvalue, frame, pbone->scale[j + 3], angle1[j]); - } - - // Add the default rotation value. - angle1[j] += pbone->value[j + 3]; - - if (panim->offset[j] != 0) { - // Read compressed position delta. - panimvalue = (const AnimValue_HL1 *)((uint8_t *)panim + panim->offset[j]); - extract_anim_value(panimvalue, frame, pbone->scale[j], position_key->mValue[j]); - } - - // Add the default position value. - position_key->mValue[j] += pbone->value[j]; - } - - position_key->mTime = rotation_key->mTime = static_cast<double>(frame); - /* The Half-Life engine uses X as forward, Y as left, Z as up. Therefore, - pitch,yaw,roll is represented as (YZX). */ - rotation_key->mValue = aiQuaternion(angle1.y, angle1.z, angle1.x); - rotation_key->mValue.Normalize(); - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_sequence_groups_info() { - if (!header_->numseqgroups) { - return; - } - - aiNode *sequence_groups_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_GROUPS); - rootnode_children_.push_back(sequence_groups_node); - - sequence_groups_node->mNumChildren = static_cast<unsigned int>(header_->numseqgroups); - sequence_groups_node->mChildren = new aiNode *[sequence_groups_node->mNumChildren]; - - const SequenceGroup_HL1 *pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex); - - unique_sequence_groups_names_.resize(header_->numseqgroups); - for (int i = 0; i < header_->numseqgroups; ++i) { - unique_sequence_groups_names_[i] = pseqgroup[i].label; - } - - // Ensure sequence groups have unique names. - unique_name_generator_.set_template_name("SequenceGroup"); - unique_name_generator_.make_unique(unique_sequence_groups_names_); - - for (int i = 0; i < header_->numseqgroups; ++i, ++pseqgroup) { - aiNode *sequence_group_node = sequence_groups_node->mChildren[i] = new aiNode(unique_sequence_groups_names_[i]); - sequence_group_node->mParent = sequence_groups_node; - - aiMetadata *md = sequence_group_node->mMetaData = aiMetadata::Alloc(1); - if (i == 0) { - /* StudioMDL does not write the file name for the default sequence group, - so we will write it. */ - md->Set(0, "File", aiString(file_path_)); - } else { - md->Set(0, "File", aiString(pseqgroup->name)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_sequence_infos() { - if (!header_->numseq) { - return; - } - - const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); - - aiNode *sequence_infos_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS); - rootnode_children_.push_back(sequence_infos_node); - - sequence_infos_node->mNumChildren = static_cast<unsigned int>(header_->numseq); - sequence_infos_node->mChildren = new aiNode *[sequence_infos_node->mNumChildren]; - - std::vector<aiNode *> sequence_info_node_children; - - int animation_index = 0; - for (int i = 0; i < header_->numseq; ++i, ++pseqdesc) { - // Clear the list of children for the upcoming sequence info node. - sequence_info_node_children.clear(); - - aiNode *sequence_info_node = sequence_infos_node->mChildren[i] = new aiNode(unique_sequence_names_[i]); - sequence_info_node->mParent = sequence_infos_node; - - // Setup sequence info node Metadata. - aiMetadata *md = sequence_info_node->mMetaData = aiMetadata::Alloc(16); - md->Set(0, "AnimationIndex", animation_index); - animation_index += pseqdesc->numblends; - - // Reference the sequence group by name. This allows us to search a particular - // sequence group by name using aiNode(s). - md->Set(1, "SequenceGroup", aiString(unique_sequence_groups_names_[pseqdesc->seqgroup])); - md->Set(2, "FramesPerSecond", pseqdesc->fps); - md->Set(3, "NumFrames", pseqdesc->numframes); - md->Set(4, "NumBlends", pseqdesc->numblends); - md->Set(5, "Activity", pseqdesc->activity); - md->Set(6, "ActivityWeight", pseqdesc->actweight); - md->Set(7, "MotionFlags", pseqdesc->motiontype); - md->Set(8, "MotionBone", temp_bones_[pseqdesc->motionbone].node->mName); - md->Set(9, "LinearMovement", aiVector3D(pseqdesc->linearmovement[0], pseqdesc->linearmovement[1], pseqdesc->linearmovement[2])); - md->Set(10, "BBMin", aiVector3D(pseqdesc->bbmin[0], pseqdesc->bbmin[1], pseqdesc->bbmin[2])); - md->Set(11, "BBMax", aiVector3D(pseqdesc->bbmax[0], pseqdesc->bbmax[1], pseqdesc->bbmax[2])); - md->Set(12, "EntryNode", pseqdesc->entrynode); - md->Set(13, "ExitNode", pseqdesc->exitnode); - md->Set(14, "NodeFlags", pseqdesc->nodeflags); - md->Set(15, "Flags", pseqdesc->flags); - - if (import_settings_.read_blend_controllers) { - int num_blend_controllers; - if (get_num_blend_controllers(pseqdesc->numblends, num_blend_controllers) && num_blend_controllers) { - // Read blend controllers info. - aiNode *blend_controllers_node = new aiNode(AI_MDL_HL1_NODE_BLEND_CONTROLLERS); - sequence_info_node_children.push_back(blend_controllers_node); - blend_controllers_node->mParent = sequence_info_node; - blend_controllers_node->mNumChildren = static_cast<unsigned int>(num_blend_controllers); - blend_controllers_node->mChildren = new aiNode *[blend_controllers_node->mNumChildren]; - - for (unsigned int j = 0; j < blend_controllers_node->mNumChildren; ++j) { - aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode(); - blend_controller_node->mParent = blend_controllers_node; - - aiMetadata *metaData = blend_controller_node->mMetaData = aiMetadata::Alloc(3); - metaData->Set(0, "Start", pseqdesc->blendstart[j]); - metaData->Set(1, "End", pseqdesc->blendend[j]); - metaData->Set(2, "MotionFlags", pseqdesc->blendtype[j]); - } - } - } - - if (import_settings_.read_animation_events && pseqdesc->numevents) { - // Read animation events. - - if (pseqdesc->numevents > AI_MDL_HL1_MAX_EVENTS) { - log_warning_limit_exceeded<AI_MDL_HL1_MAX_EVENTS>( - "Sequence " + std::string(pseqdesc->label), - pseqdesc->numevents, "animation events"); - } - - const AnimEvent_HL1 *pevent = (const AnimEvent_HL1 *)((uint8_t *)header_ + pseqdesc->eventindex); - - aiNode *pEventsNode = new aiNode(AI_MDL_HL1_NODE_ANIMATION_EVENTS); - sequence_info_node_children.push_back(pEventsNode); - pEventsNode->mParent = sequence_info_node; - pEventsNode->mNumChildren = static_cast<unsigned int>(pseqdesc->numevents); - pEventsNode->mChildren = new aiNode *[pEventsNode->mNumChildren]; - - for (unsigned int j = 0; j < pEventsNode->mNumChildren; ++j, ++pevent) { - aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode(); - pEvent->mParent = pEventsNode; - - aiMetadata *metaData = pEvent->mMetaData = aiMetadata::Alloc(3); - metaData->Set(0, "Frame", pevent->frame); - metaData->Set(1, "ScriptEvent", pevent->event); - metaData->Set(2, "Options", aiString(pevent->options)); - } - } - - if (sequence_info_node_children.size()) { - sequence_info_node->addChildren( - static_cast<unsigned int>(sequence_info_node_children.size()), - sequence_info_node_children.data()); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_sequence_transitions() { - if (!header_->numtransitions) { - return; - } - - // Read sequence transition graph. - aiNode *transition_graph_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH); - rootnode_children_.push_back(transition_graph_node); - - uint8_t *ptransitions = ((uint8_t *)header_ + header_->transitionindex); - aiMetadata *md = transition_graph_node->mMetaData = aiMetadata::Alloc(header_->numtransitions * header_->numtransitions); - for (unsigned int i = 0; i < md->mNumProperties; ++i) - md->Set(i, std::to_string(i), static_cast<int>(ptransitions[i])); -} - -void HL1MDLLoader::read_attachments() { - if (!header_->numattachments) { - return; - } - - const Attachment_HL1 *pattach = (const Attachment_HL1 *)((uint8_t *)header_ + header_->attachmentindex); - - aiNode *attachments_node = new aiNode(AI_MDL_HL1_NODE_ATTACHMENTS); - rootnode_children_.push_back(attachments_node); - attachments_node->mNumChildren = static_cast<unsigned int>(header_->numattachments); - attachments_node->mChildren = new aiNode *[attachments_node->mNumChildren]; - - for (int i = 0; i < header_->numattachments; ++i, ++pattach) { - aiNode *attachment_node = attachments_node->mChildren[i] = new aiNode(); - attachment_node->mParent = attachments_node; - attachment_node->mMetaData = aiMetadata::Alloc(2); - attachment_node->mMetaData->Set(0, "Position", aiVector3D(pattach->org[0], pattach->org[1], pattach->org[2])); - // Reference the bone by name. This allows us to search a particular - // bone by name using aiNode(s). - attachment_node->mMetaData->Set(1, "Bone", temp_bones_[pattach->bone].node->mName); - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_hitboxes() { - if (!header_->numhitboxes) { - return; - } - - const Hitbox_HL1 *phitbox = (const Hitbox_HL1 *)((uint8_t *)header_ + header_->hitboxindex); - - aiNode *hitboxes_node = new aiNode(AI_MDL_HL1_NODE_HITBOXES); - rootnode_children_.push_back(hitboxes_node); - hitboxes_node->mNumChildren = static_cast<unsigned int>(header_->numhitboxes); - hitboxes_node->mChildren = new aiNode *[hitboxes_node->mNumChildren]; - - for (int i = 0; i < header_->numhitboxes; ++i, ++phitbox) { - aiNode *hitbox_node = hitboxes_node->mChildren[i] = new aiNode(); - hitbox_node->mParent = hitboxes_node; - - aiMetadata *md = hitbox_node->mMetaData = aiMetadata::Alloc(4); - // Reference the bone by name. This allows us to search a particular - // bone by name using aiNode(s). - md->Set(0, "Bone", temp_bones_[phitbox->bone].node->mName); - md->Set(1, "HitGroup", phitbox->group); - md->Set(2, "BBMin", aiVector3D(phitbox->bbmin[0], phitbox->bbmin[1], phitbox->bbmin[2])); - md->Set(3, "BBMax", aiVector3D(phitbox->bbmax[0], phitbox->bbmax[1], phitbox->bbmax[2])); - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_bone_controllers() { - if (!header_->numbonecontrollers) { - return; - } - - const BoneController_HL1 *pbonecontroller = (const BoneController_HL1 *)((uint8_t *)header_ + header_->bonecontrollerindex); - - aiNode *bones_controller_node = new aiNode(AI_MDL_HL1_NODE_BONE_CONTROLLERS); - rootnode_children_.push_back(bones_controller_node); - bones_controller_node->mNumChildren = static_cast<unsigned int>(header_->numbonecontrollers); - bones_controller_node->mChildren = new aiNode *[bones_controller_node->mNumChildren]; - - for (int i = 0; i < header_->numbonecontrollers; ++i, ++pbonecontroller) { - aiNode *bone_controller_node = bones_controller_node->mChildren[i] = new aiNode(); - bone_controller_node->mParent = bones_controller_node; - - aiMetadata *md = bone_controller_node->mMetaData = aiMetadata::Alloc(5); - // Reference the bone by name. This allows us to search a particular - // bone by name using aiNode(s). - md->Set(0, "Bone", temp_bones_[pbonecontroller->bone].node->mName); - md->Set(1, "MotionFlags", pbonecontroller->type); - md->Set(2, "Start", pbonecontroller->start); - md->Set(3, "End", pbonecontroller->end); - md->Set(4, "Channel", pbonecontroller->index); - } -} - -// ------------------------------------------------------------------------------------------------ -void HL1MDLLoader::read_global_info() { - aiNode *global_info_node = new aiNode(AI_MDL_HL1_NODE_GLOBAL_INFO); - rootnode_children_.push_back(global_info_node); - - aiMetadata *md = global_info_node->mMetaData = aiMetadata::Alloc(import_settings_.read_misc_global_info ? 16 : 11); - md->Set(0, "Version", AI_MDL_HL1_VERSION); - md->Set(1, "NumBodyparts", header_->numbodyparts); - md->Set(2, "NumModels", total_models_); - md->Set(3, "NumBones", header_->numbones); - md->Set(4, "NumAttachments", import_settings_.read_attachments ? header_->numattachments : 0); - md->Set(5, "NumSkinFamilies", texture_header_->numskinfamilies); - md->Set(6, "NumHitboxes", import_settings_.read_hitboxes ? header_->numhitboxes : 0); - md->Set(7, "NumBoneControllers", import_settings_.read_bone_controllers ? header_->numbonecontrollers : 0); - md->Set(8, "NumSequences", import_settings_.read_animations ? header_->numseq : 0); - md->Set(9, "NumBlendControllers", import_settings_.read_blend_controllers ? num_blend_controllers_ : 0); - md->Set(10, "NumTransitionNodes", import_settings_.read_sequence_transitions ? header_->numtransitions : 0); - - if (import_settings_.read_misc_global_info) { - md->Set(11, "EyePosition", aiVector3D(header_->eyeposition[0], header_->eyeposition[1], header_->eyeposition[2])); - md->Set(12, "HullMin", aiVector3D(header_->min[0], header_->min[1], header_->min[2])); - md->Set(13, "HullMax", aiVector3D(header_->max[0], header_->max[1], header_->max[2])); - md->Set(14, "CollisionMin", aiVector3D(header_->bbmin[0], header_->bbmin[1], header_->bbmin[2])); - md->Set(15, "CollisionMax", aiVector3D(header_->bbmax[0], header_->bbmax[1], header_->bbmax[2])); - } -} - -// ------------------------------------------------------------------------------------------------ -/** @brief This method reads a compressed anim value. -* -* @note The structure of this method is taken from HL2 source code. -* Although this is from HL2, it's implementation is almost identical -* to code found in HL1 SDK. See HL1 and HL2 SDKs for more info. -* -* source: -* HL1 source code. -* file: studio_render.cpp -* function(s): CalcBoneQuaternion and CalcBonePosition -* -* HL2 source code. -* file: bone_setup.cpp -* function(s): ExtractAnimValue -*/ -void HL1MDLLoader::extract_anim_value( - const AnimValue_HL1 *panimvalue, - int frame, float bone_scale, ai_real &value) { - int k = frame; - - // find span of values that includes the frame we want - while (panimvalue->num.total <= k) { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - } - - // Bah, missing blend! - if (panimvalue->num.valid > k) { - value = panimvalue[k + 1].value * bone_scale; - } else { - value = panimvalue[panimvalue->num.valid].value * bone_scale; - } -} - -// ------------------------------------------------------------------------------------------------ -// Get the number of blend controllers. -bool HL1MDLLoader::get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers) { - - switch (num_blend_animations) { - case SequenceBlendMode_HL1::NoBlend: - num_blend_controllers = 0; - return true; - case SequenceBlendMode_HL1::TwoWayBlending: - num_blend_controllers = 1; - return true; - case SequenceBlendMode_HL1::FourWayBlending: - num_blend_controllers = 2; - return true; - default: - num_blend_controllers = 0; - ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (", num_blend_animations, ")"); - return false; - } -} - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h deleted file mode 100644 index d87d6d3..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h +++ /dev/null @@ -1,243 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1MDLLoader.h - * @brief Declaration of the Half-Life 1 MDL loader. - */ - -#ifndef AI_HL1MDLLOADER_INCLUDED -#define AI_HL1MDLLOADER_INCLUDED - -#include "HL1FileData.h" -#include "HL1ImportSettings.h" -#include "UniqueNameGenerator.h" - -#include <memory> -#include <string> - -#include <assimp/types.h> -#include <assimp/scene.h> -#include <assimp/texture.h> -#include <assimp/IOSystem.hpp> -#include <assimp/DefaultIOSystem.h> -#include <assimp/Exceptional.h> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -class HL1MDLLoader { -public: - HL1MDLLoader() = delete; - HL1MDLLoader(const HL1MDLLoader &) = delete; - - /** See variables descriptions at the end for more details. */ - HL1MDLLoader( - aiScene *scene, - IOSystem *io, - const unsigned char *buffer, - const std::string &file_path, - const HL1ImportSettings &import_settings); - - ~HL1MDLLoader(); - - void load_file(); - -protected: - /** \brief Validate the header data structure of a Half-Life 1 MDL file. - * \param[in] header Input header to be validated. - * \param[in] is_texture_header Whether or not we are reading an MDL - * texture file. - */ - void validate_header(const Header_HL1 *header, bool is_texture_header); - - void load_texture_file(); - void load_sequence_groups_files(); - void read_textures(); - void read_skins(); - void read_bones(); - void read_meshes(); - void read_animations(); - void read_sequence_groups_info(); - void read_sequence_infos(); - void read_sequence_transitions(); - void read_attachments(); - void read_hitboxes(); - void read_bone_controllers(); - void read_global_info(); - -private: - void release_resources(); - - /** \brief Load a file and copy it's content to a buffer. - * \param file_path The path to the file to be loaded. - * \param buffer A pointer to a buffer to receive the data. - */ - template <typename MDLFileHeader> - void load_file_into_buffer(const std::string &file_path, unsigned char *&buffer); - - /** \brief Read an MDL texture. - * \param[in] ptexture A pointer to an MDL texture. - * \param[in] data A pointer to the data from \p ptexture. - * \param[in] pal A pointer to the texture palette from \p ptexture. - * \param[in,out] pResult A pointer to the output resulting Assimp texture. - * \param[in,out] last_palette_color The last color from the image palette. - */ - void read_texture(const Texture_HL1 *ptexture, - uint8_t *data, uint8_t *pal, aiTexture *pResult, - aiColor3D &last_palette_color); - - /** \brief This method reads a compressed anim value. - * \param[in] panimvalue A pointer to the animation data. - * \param[in] frame The frame to look for. - * \param[in] bone_scale The current bone scale to apply to the compressed value. - * \param[in,out] value The decompressed anim value at \p frame. - */ - void extract_anim_value(const AnimValue_HL1 *panimvalue, - int frame, float bone_scale, ai_real &value); - - /** - * \brief Given the number of blend animations, determine the number of blend controllers. - * - * \param[in] num_blend_animations The number of blend animations. - * \param[out] num_blend_controllers The number of blend controllers. - * \return True if the number of blend controllers was determined. False otherwise. - */ - static bool get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers); - - /** Output scene to be filled */ - aiScene *scene_; - - /** Output I/O handler. Required for additional IO operations. */ - IOSystem *io_; - - /** Buffer from MDLLoader class. */ - const unsigned char *buffer_; - - /** The full file path to the MDL file we are trying to load. - * Used to locate other MDL files since MDL may store resources - * in external MDL files. */ - const std::string &file_path_; - - /** Configuration for HL1 MDL */ - const HL1ImportSettings &import_settings_; - - /** Main MDL header. */ - const Header_HL1 *header_; - - /** External MDL texture header. */ - const Header_HL1 *texture_header_; - - /** External MDL animation headers. - * One for each loaded animation file. */ - SequenceHeader_HL1 **anim_headers_; - - /** Texture file data. */ - unsigned char *texture_buffer_; - - /** Animation files data. */ - unsigned char **anim_buffers_; - - /** The number of sequence groups. */ - int num_sequence_groups_; - - /** The list of children to be appended to the scene's root node. */ - std::vector<aiNode *> rootnode_children_; - - /** A unique name generator. Used to generate names for MDL values - * that may have empty/duplicate names. */ - UniqueNameGenerator unique_name_generator_; - - /** The list of unique sequence names. */ - std::vector<std::string> unique_sequence_names_; - - /** The list of unique sequence groups names. */ - std::vector<std::string> unique_sequence_groups_names_; - - /** Structure to store temporary bone information. */ - struct TempBone { - - TempBone() : - node(nullptr), - absolute_transform(), - offset_matrix() {} - - aiNode *node; - aiMatrix4x4 absolute_transform; - aiMatrix4x4 offset_matrix; - }; - - std::vector<TempBone> temp_bones_; - - /** The number of available bone controllers in the model. */ - int num_blend_controllers_; - - /** Self explanatory. */ - int total_models_; -}; - -// ------------------------------------------------------------------------------------------------ -template <typename MDLFileHeader> -void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned char *&buffer) { - if (!io_->Exists(file_path)) - throw DeadlyImportError("Missing file ", DefaultIOSystem::fileName(file_path), "."); - - std::unique_ptr<IOStream> file(io_->Open(file_path)); - - if (file.get() == nullptr) { - throw DeadlyImportError("Failed to open MDL file ", DefaultIOSystem::fileName(file_path), "."); - } - - const size_t file_size = file->FileSize(); - if (file_size < sizeof(MDLFileHeader)) { - throw DeadlyImportError("MDL file is too small."); - } - - buffer = new unsigned char[1 + file_size]; - file->Read((void *)buffer, 1, file_size); - buffer[file_size] = '\0'; -} - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_HL1MDLLOADER_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h deleted file mode 100644 index 4ef8a13..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h +++ /dev/null @@ -1,127 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HL1MeshTrivert.h - * @brief This file contains the class declaration for the - * HL1 mesh trivert class. - */ - -#ifndef AI_HL1MESHTRIVERT_INCLUDED -#define AI_HL1MESHTRIVERT_INCLUDED - -#include "HL1FileData.h" - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -/* A class to help map model triverts to mesh triverts. */ -struct HL1MeshTrivert { - HL1MeshTrivert() : - vertindex(-1), - normindex(-1), - s(0), - t(0), - localindex(-1) { - } - - HL1MeshTrivert(short vertindex, short normindex, short s, short t, short localindex) : - vertindex(vertindex), - normindex(normindex), - s(s), - t(t), - localindex(localindex) { - } - - HL1MeshTrivert(const Trivert &a) : - vertindex(a.vertindex), - normindex(a.normindex), - s(a.s), - t(a.t), - localindex(-1) { - } - - inline bool operator==(const Trivert &a) const { - return vertindex == a.vertindex && - normindex == a.normindex && - s == a.s && - t == a.t; - } - - inline bool operator!=(const Trivert &a) const { - return !(*this == a); - } - - inline bool operator==(const HL1MeshTrivert &a) const { - return localindex == a.localindex && - vertindex == a.vertindex && - normindex == a.normindex && - s == a.s && - t == a.t; - } - - inline bool operator!=(const HL1MeshTrivert &a) const { - return !(*this == a); - } - - inline HL1MeshTrivert &operator=(const Trivert &other) { - vertindex = other.vertindex; - normindex = other.normindex; - s = other.s; - t = other.t; - return *this; - } - - short vertindex; - short normindex; - short s, t; - short localindex; -}; - -struct HL1MeshFace { - short v0, v1, v2; -}; - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_HL1MESHTRIVERT_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h b/libs/assimp/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h deleted file mode 100644 index c7808c4..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h +++ /dev/null @@ -1,67 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file HalfLifeMDLBaseHeader.h */ - -#ifndef AI_HALFLIFEMDLBASEHEADER_INCLUDED -#define AI_HALFLIFEMDLBASEHEADER_INCLUDED - -#include <assimp/types.h> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -/** Used to interface different Valve MDL formats. */ -struct HalfLifeMDLBaseHeader -{ - //! Magic number: "IDST"/"IDSQ" - char ident[4]; - - //! The file format version. - int32_t version; -}; - -} -} -} - -#endif // AI_HALFLIFEMDLBASEHEADER_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/LogFunctions.h b/libs/assimp/code/AssetLib/MDL/HalfLife/LogFunctions.h deleted file mode 100644 index 003774d..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/LogFunctions.h +++ /dev/null @@ -1,95 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file LogFunctions.h */ - -#ifndef AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED -#define AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED - -#include <assimp/Logger.hpp> -#include <string> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -/** - * \brief A function to log precise messages regarding limits exceeded. - * - * \param[in] subject Subject. - * \param[in] current_amount Current amount. - * \param[in] direct_object Direct object. - * LIMIT Limit constant. - * - * Example: Model has 100 textures, which exceeds the limit (50) - * - * where \p subject is 'Model' - * \p current_amount is '100' - * \p direct_object is 'textures' - * LIMIT is '50' - */ -template <int LIMIT> -static inline void log_warning_limit_exceeded( - const std::string &subject, int current_amount, - const std::string &direct_object) { - - ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER - + subject - + " has " - + std::to_string(current_amount) + " " - + direct_object - + ", which exceeds the limit (" - + std::to_string(LIMIT) - + ")"); -} - -/** \brief Same as above, but uses 'Model' as the subject. */ -template <int LIMIT> -static inline void log_warning_limit_exceeded(int current_amount, - const std::string &direct_object) { - log_warning_limit_exceeded<LIMIT>("Model", current_amount, direct_object); -} - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp b/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp deleted file mode 100644 index 6fc8b11..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file UniqueNameGenerator.cpp - * @brief Implementation for the unique name generator. - */ - -#include "UniqueNameGenerator.h" -#include <algorithm> -#include <list> -#include <map> -#include <numeric> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -UniqueNameGenerator::UniqueNameGenerator() : - template_name_("unnamed"), - separator_("_") { -} - -UniqueNameGenerator::UniqueNameGenerator(const char *template_name) : - template_name_(template_name), - separator_("_") { -} - -UniqueNameGenerator::UniqueNameGenerator(const char *template_name, const char *separator) : - template_name_(template_name), - separator_(separator) { -} - -UniqueNameGenerator::~UniqueNameGenerator() { -} - -void UniqueNameGenerator::make_unique(std::vector<std::string> &names) { - struct DuplicateInfo { - DuplicateInfo() : - indices(), - next_id(0) { - } - - std::list<size_t> indices; - size_t next_id; - }; - - std::vector<size_t> empty_names_indices; - std::vector<size_t> template_name_duplicates; - std::map<std::string, DuplicateInfo> names_to_duplicates; - - const std::string template_name_with_separator(template_name_ + separator_); - - auto format_name = [&](const std::string &base_name, size_t id) -> std::string { - return base_name + separator_ + std::to_string(id); - }; - - auto generate_unique_name = [&](const std::string &base_name) -> std::string { - auto *duplicate_info = &names_to_duplicates[base_name]; - - std::string new_name; - - bool found_identical_name; - bool tried_with_base_name_only = false; - do { - // Assume that no identical name exists. - found_identical_name = false; - - if (!tried_with_base_name_only) { - // First try with only the base name. - new_name = base_name; - } else { - // Create the name expected to be unique. - new_name = format_name(base_name, duplicate_info->next_id); - } - - // Check in the list of duplicates for an identical name. - for (size_t i = 0; - i < names.size() && - !found_identical_name; - ++i) { - if (new_name == names[i]) - found_identical_name = true; - } - - if (tried_with_base_name_only) - ++duplicate_info->next_id; - - tried_with_base_name_only = true; - - } while (found_identical_name); - - return new_name; - }; - - for (size_t i = 0; i < names.size(); ++i) { - // Check for empty names. - if (names[i].find_first_not_of(' ') == std::string::npos) { - empty_names_indices.push_back(i); - continue; - } - - /* Check for potential duplicate. - a) Either if this name is the same as the template name or - b) <template name><separator> is found at the beginning. */ - if (names[i] == template_name_ || - names[i].substr(0, template_name_with_separator.length()) == template_name_with_separator) - template_name_duplicates.push_back(i); - - // Map each unique name to it's duplicate. - if (names_to_duplicates.count(names[i]) == 0) - names_to_duplicates.insert({ names[i], DuplicateInfo()}); - else - names_to_duplicates[names[i]].indices.push_back(i); - } - - // Make every non-empty name unique. - for (auto it = names_to_duplicates.begin(); - it != names_to_duplicates.end(); ++it) { - for (auto it2 = it->second.indices.begin(); - it2 != it->second.indices.end(); - ++it2) - names[*it2] = generate_unique_name(it->first); - } - - // Generate a unique name for every empty string. - if (template_name_duplicates.size()) { - // At least one string ressembles to <template name>. - for (auto it = empty_names_indices.begin(); - it != empty_names_indices.end(); ++it) - names[*it] = generate_unique_name(template_name_); - } else { - // No string alike <template name> exists. - size_t i = 0; - for (auto it = empty_names_indices.begin(); - it != empty_names_indices.end(); ++it, ++i) - names[*it] = format_name(template_name_, i); - } -} - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp diff --git a/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h b/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h deleted file mode 100644 index 73b6f9e..0000000 --- a/libs/assimp/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h +++ /dev/null @@ -1,81 +0,0 @@ -/* ---------------------------------------------------------------------------- -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. ---------------------------------------------------------------------------- -*/ - -/** @file UniqueNameGenerator.h - * @brief Declaration of the unique name generator. - */ - -#ifndef AI_UNIQUENAMEGENERATOR_INCLUDED -#define AI_UNIQUENAMEGENERATOR_INCLUDED - -#include <string> -#include <vector> - -namespace Assimp { -namespace MDL { -namespace HalfLife { - -class UniqueNameGenerator { -public: - UniqueNameGenerator(); - UniqueNameGenerator(const char *template_name); - UniqueNameGenerator(const char *template_name, const char *separator); - ~UniqueNameGenerator(); - - inline void set_template_name(const char *template_name) { - template_name_ = template_name; - } - inline void set_separator(const char *separator) { - separator_ = separator; - } - - void make_unique(std::vector<std::string> &names); - -private: - std::string template_name_; - std::string separator_; -}; - -} // namespace HalfLife -} // namespace MDL -} // namespace Assimp - -#endif // AI_UNIQUENAMEGENERATOR_INCLUDED |