diff options
Diffstat (limited to 'libs/assimp/code/AssetLib/MD5')
-rw-r--r-- | libs/assimp/code/AssetLib/MD5/MD5Loader.cpp | 735 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/MD5/MD5Loader.h | 181 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/MD5/MD5Parser.cpp | 472 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/MD5/MD5Parser.h | 467 |
4 files changed, 0 insertions, 1855 deletions
diff --git a/libs/assimp/code/AssetLib/MD5/MD5Loader.cpp b/libs/assimp/code/AssetLib/MD5/MD5Loader.cpp deleted file mode 100644 index 2d5da4d..0000000 --- a/libs/assimp/code/AssetLib/MD5/MD5Loader.cpp +++ /dev/null @@ -1,735 +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 MD5Loader.cpp - * @brief Implementation of the MD5 importer class - */ - -#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER - -// internal headers -#include "MD5Loader.h" -#include <assimp/MathFunctions.h> -#include <assimp/RemoveComments.h> -#include <assimp/SkeletonMeshBuilder.h> -#include <assimp/StringComparison.h> -#include <assimp/fast_atof.h> -#include <assimp/importerdesc.h> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/IOSystem.hpp> -#include <assimp/Importer.hpp> -#include <memory> - -using namespace Assimp; - -// Minimum weight value. Weights inside [-n ... n] are ignored -#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>() - -static const aiImporterDesc desc = { - "Doom 3 / MD5 Mesh Importer", - "", - "", - "", - aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, - "md5mesh md5camera md5anim" -}; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MD5Importer::MD5Importer() : - mIOHandler(nullptr), - mBuffer(), - mFileSize(), - mLineNumber(), - mScene(), - mHadMD5Mesh(), - mHadMD5Anim(), - mHadMD5Camera(), - mCconfigNoAutoLoad(false) { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD5Importer::~MD5Importer() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { - static const char *tokens[] = { "MD5Version" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); -} - -// ------------------------------------------------------------------------------------------------ -// Get list of all supported extensions -const aiImporterDesc *MD5Importer::GetInfo() const { - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Setup import properties -void MD5Importer::SetupProperties(const Importer *pImp) { - // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD - mCconfigNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MD5Importer::InternReadFile(const std::string &pFile, aiScene *_pScene, IOSystem *pIOHandler) { - mIOHandler = pIOHandler; - mScene = _pScene; - mHadMD5Mesh = mHadMD5Anim = mHadMD5Camera = false; - - // remove the file extension - const std::string::size_type pos = pFile.find_last_of('.'); - mFile = (std::string::npos == pos ? pFile : pFile.substr(0, pos + 1)); - - const std::string extension = GetExtension(pFile); - try { - if (extension == "md5camera") { - LoadMD5CameraFile(); - } else if (mCconfigNoAutoLoad || extension == "md5anim") { - // determine file extension and process just *one* file - if (extension.length() == 0) { - throw DeadlyImportError("Failure, need file extension to determine MD5 part type"); - } - if (extension == "md5anim") { - LoadMD5AnimFile(); - } else if (extension == "md5mesh") { - LoadMD5MeshFile(); - } - } else { - LoadMD5MeshFile(); - LoadMD5AnimFile(); - } - } catch (...) { // std::exception, Assimp::DeadlyImportError - UnloadFileFromMemory(); - throw; - } - - // make sure we have at least one file - if (!mHadMD5Mesh && !mHadMD5Anim && !mHadMD5Camera) { - throw DeadlyImportError("Failed to read valid contents out of this MD5* file"); - } - - // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system - mScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); - - // the output scene wouldn't pass the validation without this flag - if (!mHadMD5Mesh) { - mScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - // clean the instance -- the BaseImporter instance may be reused later. - UnloadFileFromMemory(); -} - -// ------------------------------------------------------------------------------------------------ -// Load a file into a memory buffer -void MD5Importer::LoadFileIntoMemory(IOStream *file) { - // unload the previous buffer, if any - UnloadFileFromMemory(); - - ai_assert(nullptr != file); - mFileSize = (unsigned int)file->FileSize(); - ai_assert(mFileSize); - - // allocate storage and copy the contents of the file to a memory buffer - mBuffer = new char[mFileSize + 1]; - file->Read((void *)mBuffer, 1, mFileSize); - mLineNumber = 1; - - // append a terminal 0 - mBuffer[mFileSize] = '\0'; - - // now remove all line comments from the file - CommentRemover::RemoveLineComments("//", mBuffer, ' '); -} - -// ------------------------------------------------------------------------------------------------ -// Unload the current memory buffer -void MD5Importer::UnloadFileFromMemory() { - // delete the file buffer - delete[] mBuffer; - mBuffer = nullptr; - mFileSize = 0; -} - -// ------------------------------------------------------------------------------------------------ -// Build unique vertices -void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) { - std::vector<bool> abHad(meshSrc.mVertices.size(), false); - - // allocate enough storage to keep the output structures - const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size() * 3); - unsigned int iNewIndex = static_cast<unsigned int>(meshSrc.mVertices.size()); - meshSrc.mVertices.resize(iNewNum); - - // try to guess how much storage we'll need for new weights - const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex; - const unsigned int guess = (unsigned int)(fWeightsPerVert * iNewNum); - meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer - - for (FaceList::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) { - const aiFace &face = *iter; - for (unsigned int i = 0; i < 3; ++i) { - if (face.mIndices[0] >= meshSrc.mVertices.size()) { - throw DeadlyImportError("MD5MESH: Invalid vertex index"); - } - - if (abHad[face.mIndices[i]]) { - // generate a new vertex - meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]]; - face.mIndices[i] = iNewIndex++; - } else - abHad[face.mIndices[i]] = true; - } - // swap face order - std::swap(face.mIndices[0], face.mIndices[2]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursive node graph construction from a MD5MESH -void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) { - ai_assert(nullptr != piParent); - ai_assert(!piParent->mNumChildren); - - // First find out how many children we'll have - for (int i = 0; i < (int)bones.size(); ++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { - ++piParent->mNumChildren; - } - } - if (piParent->mNumChildren) { - piParent->mChildren = new aiNode *[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size(); ++i) { - // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) { - aiNode *pc; - // setup a new node - *piParent->mChildren++ = pc = new aiNode(); - pc->mName = aiString(bones[i].mName); - pc->mParent = piParent; - - // get the transformation matrix from rotation and translational components - aiQuaternion quat; - MD5::ConvertQuaternion(bones[i].mRotationQuat, quat); - - bones[i].mTransform = aiMatrix4x4(quat.GetMatrix()); - bones[i].mTransform.a4 = bones[i].mPositionXYZ.x; - bones[i].mTransform.b4 = bones[i].mPositionXYZ.y; - bones[i].mTransform.c4 = bones[i].mPositionXYZ.z; - - // store it for later use - pc->mTransformation = bones[i].mInvTransform = bones[i].mTransform; - bones[i].mInvTransform.Inverse(); - - // the transformations for each bone are absolute, so we need to multiply them - // with the inverse of the absolute matrix of the parent joint - if (-1 != iParentID) { - pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation; - } - - // add children to this node, too - AttachChilds_Mesh(i, pc, bones); - } - } - // undo offset computations - piParent->mChildren -= piParent->mNumChildren; - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursive node graph construction from a MD5ANIM -void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) { - ai_assert(nullptr != piParent); - ai_assert(!piParent->mNumChildren); - - // First find out how many children we'll have - for (int i = 0; i < (int)bones.size(); ++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { - ++piParent->mNumChildren; - } - } - if (piParent->mNumChildren) { - piParent->mChildren = new aiNode *[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size(); ++i) { - // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) { - aiNode *pc; - // setup a new node - *piParent->mChildren++ = pc = new aiNode(); - pc->mName = aiString(bones[i].mName); - pc->mParent = piParent; - - // get the corresponding animation channel and its first frame - const aiNodeAnim **cur = node_anims; - while ((**cur).mNodeName != pc->mName) - ++cur; - - aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue, pc->mTransformation); - pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()); - - // add children to this node, too - AttachChilds_Anim(i, pc, bones, node_anims); - } - } - // undo offset computations - piParent->mChildren -= piParent->mNumChildren; - } -} - -// ------------------------------------------------------------------------------------------------ -// Load a MD5MESH file -void MD5Importer::LoadMD5MeshFile() { - std::string filename = mFile + "md5mesh"; - std::unique_ptr<IOStream> file(mIOHandler->Open(filename, "rb")); - - // Check whether we can read from the file - if (file.get() == nullptr || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to access MD5MESH file: ", filename); - return; - } - mHadMD5Mesh = true; - LoadFileIntoMemory(file.get()); - - // now construct a parser and parse the file - MD5::MD5Parser parser(mBuffer, mFileSize); - - // load the mesh information from it - MD5::MD5MeshParser meshParser(parser.mSections); - - // create the bone hierarchy - first the root node and dummy nodes for all meshes - mScene->mRootNode = new aiNode("<MD5_Root>"); - mScene->mRootNode->mNumChildren = 2; - mScene->mRootNode->mChildren = new aiNode *[2]; - - // build the hierarchy from the MD5MESH file - aiNode *pcNode = mScene->mRootNode->mChildren[1] = new aiNode(); - pcNode->mName.Set("<MD5_Hierarchy>"); - pcNode->mParent = mScene->mRootNode; - AttachChilds_Mesh(-1, pcNode, meshParser.mJoints); - - pcNode = mScene->mRootNode->mChildren[0] = new aiNode(); - pcNode->mName.Set("<MD5_Mesh>"); - pcNode->mParent = mScene->mRootNode; - -#if 0 - if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */ - SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[1]->mChildren[0]); -#else - - // FIX: MD5 files exported from Blender can have empty meshes - for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { - if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) { - ++mScene->mNumMaterials; - } - } - - // generate all meshes - mScene->mNumMeshes = mScene->mNumMaterials; - mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; - mScene->mMaterials = new aiMaterial *[mScene->mNumMeshes]; - - // storage for node mesh indices - pcNode->mNumMeshes = mScene->mNumMeshes; - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) { - pcNode->mMeshes[m] = m; - } - - unsigned int n = 0; - for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { - MD5::MeshDesc &meshSrc = *it; - if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) { - continue; - } - - aiMesh *mesh = mScene->mMeshes[n] = new aiMesh(); - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // generate unique vertices in our internal verbose format - MakeDataUnique(meshSrc); - - std::string name(meshSrc.mShader.C_Str()); - name += ".msh"; - mesh->mName = name; - mesh->mNumVertices = (unsigned int)meshSrc.mVertices.size(); - mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; - - // copy texture coordinates - aiVector3D *pv = mesh->mTextureCoords[0]; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { - pv->x = (*iter).mUV.x; - pv->y = 1.0f - (*iter).mUV.y; // D3D to OpenGL - pv->z = 0.0f; - } - - // sort all bone weights - per bone - unsigned int *piCount = new unsigned int[meshParser.mJoints.size()]; - ::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size()); - - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { - MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; - /* FIX for some invalid exporters */ - if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) { - ++piCount[weightDesc.mBone]; - } - } - } - - // check how many we will need - for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) { - if (piCount[p]) mesh->mNumBones++; - } - - // just for safety - if (mesh->mNumBones) { - mesh->mBones = new aiBone *[mesh->mNumBones]; - for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) { - if (!piCount[q]) continue; - aiBone *p = mesh->mBones[h] = new aiBone(); - p->mNumWeights = piCount[q]; - p->mWeights = new aiVertexWeight[p->mNumWeights]; - p->mName = aiString(meshParser.mJoints[q].mName); - p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform; - - // store the index for later use - MD5::BoneDesc &boneSrc = meshParser.mJoints[q]; - boneSrc.mMap = h++; - - // compute w-component of quaternion - MD5::ConvertQuaternion(boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted); - } - - pv = mesh->mVertices; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { - // compute the final vertex position from all single weights - *pv = aiVector3D(); - - // there are models which have weights which don't sum to 1 ... - ai_real fSum = 0.0; - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { - fSum += meshSrc.mWeights[w].mWeight; - } - if (!fSum) { - ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); - continue; - } - - // process bone weights - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { - if (w >= meshSrc.mWeights.size()) { - throw DeadlyImportError("MD5MESH: Invalid weight index"); - } - - MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; - if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { - continue; - } - - const ai_real fNewWeight = weightDesc.mWeight / fSum; - - // transform the local position into worldspace - MD5::BoneDesc &boneSrc = meshParser.mJoints[weightDesc.mBone]; - const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate(weightDesc.vOffsetPosition); - - // use the original weight to compute the vertex position - // (some MD5s seem to depend on the invalid weight values ...) - *pv += ((boneSrc.mPositionXYZ + v) * (ai_real)weightDesc.mWeight); - - aiBone *bone = mesh->mBones[boneSrc.mMap]; - *bone->mWeights++ = aiVertexWeight((unsigned int)(pv - mesh->mVertices), fNewWeight); - } - } - - // undo our nice offset tricks ... - for (unsigned int p = 0; p < mesh->mNumBones; ++p) { - mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights; - } - } - - delete[] piCount; - - // now setup all faces - we can directly copy the list - // (however, take care that the aiFace destructor doesn't delete the mIndices array) - mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size(); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - for (unsigned int c = 0; c < mesh->mNumFaces; ++c) { - mesh->mFaces[c].mNumIndices = 3; - mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices; - meshSrc.mFaces[c].mIndices = nullptr; - } - - // generate a material for the mesh - aiMaterial *mat = new aiMaterial(); - mScene->mMaterials[n] = mat; - - // insert the typical doom3 textures: - // nnn_local.tga - normal map - // nnn_h.tga - height map - // nnn_s.tga - specular map - // nnn_d.tga - diffuse map - if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data, '.')) { - - aiString temp(meshSrc.mShader); - temp.Append("_local.tga"); - mat->AddProperty(&temp, AI_MATKEY_TEXTURE_NORMALS(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_s.tga"); - mat->AddProperty(&temp, AI_MATKEY_TEXTURE_SPECULAR(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_d.tga"); - mat->AddProperty(&temp, AI_MATKEY_TEXTURE_DIFFUSE(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_h.tga"); - mat->AddProperty(&temp, AI_MATKEY_TEXTURE_HEIGHT(0)); - - // set this also as material name - mat->AddProperty(&meshSrc.mShader, AI_MATKEY_NAME); - } else { - mat->AddProperty(&meshSrc.mShader, AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - mesh->mMaterialIndex = n++; - } -#endif -} - -// ------------------------------------------------------------------------------------------------ -// Load an MD5ANIM file -void MD5Importer::LoadMD5AnimFile() { - std::string pFile = mFile + "md5anim"; - std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (!file.get() || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to read MD5ANIM file: ", pFile); - return; - } - - LoadFileIntoMemory(file.get()); - - // parse the basic file structure - MD5::MD5Parser parser(mBuffer, mFileSize); - - // load the animation information from the parse tree - MD5::MD5AnimParser animParser(parser.mSections); - - // generate and fill the output animation - if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() || - animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { - ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); - } else { - mHadMD5Anim = true; - - mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations = 1]; - aiAnimation *anim = mScene->mAnimations[0] = new aiAnimation(); - anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); - anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; - for (unsigned int i = 0; i < anim->mNumChannels; ++i) { - aiNodeAnim *node = anim->mChannels[i] = new aiNodeAnim(); - node->mNodeName = aiString(animParser.mAnimatedBones[i].mName); - - // allocate storage for the keyframes - node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()]; - node->mRotationKeys = new aiQuatKey[animParser.mFrames.size()]; - } - - // 1 tick == 1 frame - anim->mTicksPerSecond = animParser.fFrameRate; - - for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) { - double dTime = (double)(*iter).iIndex; - aiNodeAnim **pcAnimNode = anim->mChannels; - if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */ - { - // now process all values in there ... read all joints - MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0]; - for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2, - ++pcAnimNode, ++pcBaseFrame) { - if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) { - - // Allow for empty frames - if ((*iter2).iFlags != 0) { - throw DeadlyImportError("MD5: Keyframe index is out of range"); - } - continue; - } - const float *fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex]; - aiNodeAnim *pcCurAnimBone = *pcAnimNode; - - aiVectorKey *vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++]; - aiQuatKey *qKey = &pcCurAnimBone->mRotationKeys[pcCurAnimBone->mNumRotationKeys++]; - aiVector3D vTemp; - - // translational component - for (unsigned int i = 0; i < 3; ++i) { - if ((*iter2).iFlags & (1u << i)) { - vKey->mValue[i] = *fpCur++; - } else - vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i]; - } - - // orientation component - for (unsigned int i = 0; i < 3; ++i) { - if ((*iter2).iFlags & (8u << i)) { - vTemp[i] = *fpCur++; - } else - vTemp[i] = pcBaseFrame->vRotationQuat[i]; - } - - MD5::ConvertQuaternion(vTemp, qKey->mValue); - qKey->mTime = vKey->mTime = dTime; - } - } - - // compute the duration of the animation - anim->mDuration = std::max(dTime, anim->mDuration); - } - - // If we didn't build the hierarchy yet (== we didn't load a MD5MESH), - // construct it now from the data given in the MD5ANIM. - if (!mScene->mRootNode) { - mScene->mRootNode = new aiNode(); - mScene->mRootNode->mName.Set("<MD5_Hierarchy>"); - - AttachChilds_Anim(-1, mScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); - - // Call SkeletonMeshBuilder to construct a mesh to represent the shape - if (mScene->mRootNode->mNumChildren) { - SkeletonMeshBuilder skeleton_maker(mScene, mScene->mRootNode->mChildren[0]); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Load an MD5CAMERA file -void MD5Importer::LoadMD5CameraFile() { - std::string pFile = mFile + "md5camera"; - std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (!file.get() || !file->FileSize()) { - throw DeadlyImportError("Failed to read MD5CAMERA file: ", pFile); - } - mHadMD5Camera = true; - LoadFileIntoMemory(file.get()); - - // parse the basic file structure - MD5::MD5Parser parser(mBuffer, mFileSize); - - // load the camera animation data from the parse tree - MD5::MD5CameraParser cameraParser(parser.mSections); - - if (cameraParser.frames.empty()) { - throw DeadlyImportError("MD5CAMERA: No frames parsed"); - } - - std::vector<unsigned int> &cuts = cameraParser.cuts; - std::vector<MD5::CameraAnimFrameDesc> &frames = cameraParser.frames; - - // Construct output graph - a simple root with a dummy child. - // The root node performs the coordinate system conversion - aiNode *root = mScene->mRootNode = new aiNode("<MD5CameraRoot>"); - root->mChildren = new aiNode *[root->mNumChildren = 1]; - root->mChildren[0] = new aiNode("<MD5Camera>"); - root->mChildren[0]->mParent = root; - - // ... but with one camera assigned to it - mScene->mCameras = new aiCamera *[mScene->mNumCameras = 1]; - aiCamera *cam = mScene->mCameras[0] = new aiCamera(); - cam->mName = "<MD5Camera>"; - - // FIXME: Fov is currently set to the first frame's value - cam->mHorizontalFOV = AI_DEG_TO_RAD(frames.front().fFOV); - - // every cut is written to a separate aiAnimation - if (!cuts.size()) { - cuts.push_back(0); - cuts.push_back(static_cast<unsigned int>(frames.size() - 1)); - } else { - cuts.insert(cuts.begin(), 0); - - if (cuts.back() < frames.size() - 1) - cuts.push_back(static_cast<unsigned int>(frames.size() - 1)); - } - - mScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1); - aiAnimation **tmp = mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations]; - for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { - - aiAnimation *anim = *tmp++ = new aiAnimation(); - anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1)); - - anim->mTicksPerSecond = cameraParser.fFrameRate; - anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1]; - aiNodeAnim *nd = anim->mChannels[0] = new aiNodeAnim(); - nd->mNodeName.Set("<MD5Camera>"); - - nd->mNumPositionKeys = nd->mNumRotationKeys = *(it + 1) - (*it); - nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; - for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) { - - nd->mPositionKeys[i].mValue = frames[*it + i].vPositionXYZ; - MD5::ConvertQuaternion(frames[*it + i].vRotationQuat, nd->mRotationKeys[i].mValue); - nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it + i; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_MD5_IMPORTER diff --git a/libs/assimp/code/AssetLib/MD5/MD5Loader.h b/libs/assimp/code/AssetLib/MD5/MD5Loader.h deleted file mode 100644 index 63fb1c3..0000000 --- a/libs/assimp/code/AssetLib/MD5/MD5Loader.h +++ /dev/null @@ -1,181 +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 MD5Loader.h - * @brief Definition of the .MD5 importer class. - * http://www.modwiki.net/wiki/MD5_(file_format) -*/ -#pragma once -#ifndef AI_MD5LOADER_H_INCLUDED -#define AI_MD5LOADER_H_INCLUDED - -#include "MD5Parser.h" -#include <assimp/BaseImporter.h> -#include <assimp/types.h> - -struct aiNode; -struct aiNodeAnim; - -namespace Assimp { - -class IOStream; -using namespace Assimp::MD5; - -// --------------------------------------------------------------------------- -/** Importer class for the MD5 file format -*/ -class MD5Importer : public BaseImporter { -public: - MD5Importer(); - ~MD5Importer() override; - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, - bool checkSig) const override; - -protected: - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details - */ - const aiImporterDesc *GetInfo() const override; - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer *pImp) override; - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile(const std::string &pFile, aiScene *pScene, - IOSystem *pIOHandler) override; - - // ------------------------------------------------------------------- - /** Load a *.MD5MESH file. - */ - void LoadMD5MeshFile(); - - // ------------------------------------------------------------------- - /** Load a *.MD5ANIM file. - */ - void LoadMD5AnimFile(); - - // ------------------------------------------------------------------- - /** Load a *.MD5CAMERA file. - */ - void LoadMD5CameraFile(); - - // ------------------------------------------------------------------- - /** Construct node hierarchy from a given MD5ANIM - * @param iParentID Current parent ID - * @param piParent Parent node to attach to - * @param bones Input bones - * @param node_anims Generated node animations - */ - void AttachChilds_Anim(int iParentID, aiNode *piParent, - AnimBoneList &bones, const aiNodeAnim **node_anims); - - // ------------------------------------------------------------------- - /** Construct node hierarchy from a given MD5MESH - * @param iParentID Current parent ID - * @param piParent Parent node to attach to - * @param bones Input bones - */ - void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones); - - // ------------------------------------------------------------------- - /** Build unique vertex buffers from a given MD5ANIM - * @param meshSrc Input data - */ - void MakeDataUnique(MD5::MeshDesc &meshSrc); - - // ------------------------------------------------------------------- - /** Load the contents of a specific file into memory and - * allocates a buffer to keep it. - * - * mBuffer is modified to point to this buffer. - * @param pFile File stream to be read - */ - void LoadFileIntoMemory(IOStream *pFile); - void UnloadFileFromMemory(); - - /** IOSystem to be used to access files */ - IOSystem *mIOHandler; - - /** Path to the file, excluding the file extension but - with the dot */ - std::string mFile; - - /** Buffer to hold the loaded file */ - char *mBuffer; - - /** Size of the file */ - unsigned int mFileSize; - - /** Current line number. For debugging purposes */ - unsigned int mLineNumber; - - /** Scene to be filled */ - aiScene *mScene; - - /** true if a MD5MESH file has already been parsed */ - bool mHadMD5Mesh; - - /** true if a MD5ANIM file has already been parsed */ - bool mHadMD5Anim; - - /** true if a MD5CAMERA file has already been parsed */ - bool mHadMD5Camera; - - /** configuration option: prevent anim autoload */ - bool mCconfigNoAutoLoad; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/MD5/MD5Parser.cpp b/libs/assimp/code/AssetLib/MD5/MD5Parser.cpp deleted file mode 100644 index 7ed23cb..0000000 --- a/libs/assimp/code/AssetLib/MD5/MD5Parser.cpp +++ /dev/null @@ -1,472 +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 MD5Parser.cpp - * @brief Implementation of the MD5 parser class - */ - -// internal headers -#include "AssetLib/MD5/MD5Loader.h" -#include "Material/MaterialSystem.h" - -#include <assimp/ParsingUtils.h> -#include <assimp/StringComparison.h> -#include <assimp/fast_atof.h> -#include <assimp/mesh.h> -#include <assimp/DefaultLogger.hpp> - -using namespace Assimp; -using namespace Assimp::MD5; - -// ------------------------------------------------------------------------------------------------ -// Parse the segment structure for an MD5 file -MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) { - ai_assert(nullptr != _buffer); - ai_assert(0 != _fileSize); - - buffer = _buffer; - fileSize = _fileSize; - lineNumber = 0; - - ASSIMP_LOG_DEBUG("MD5Parser begin"); - - // parse the file header - ParseHeader(); - - // and read all sections until we're finished - bool running = true; - while (running) { - mSections.push_back(Section()); - Section &sec = mSections.back(); - if (!ParseSection(sec)) { - break; - } - } - - if (!DefaultLogger::isNullLogger()) { - char szBuffer[128]; // should be sufficiently large - ::ai_snprintf(szBuffer, 128, "MD5Parser end. Parsed %i sections", (int)mSections.size()); - ASSIMP_LOG_DEBUG(szBuffer); - } -} - -// ------------------------------------------------------------------------------------------------ -// Report error to the log stream -/*static*/ AI_WONT_RETURN void MD5Parser::ReportError(const char *error, unsigned int line) { - char szBuffer[1024]; - ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s", line, error); - throw DeadlyImportError(szBuffer); -} - -// ------------------------------------------------------------------------------------------------ -// Report warning to the log stream -/*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) { - char szBuffer[1024]; - ::sprintf(szBuffer, "[MD5] Line %u: %s", line, warn); - ASSIMP_LOG_WARN(szBuffer); -} - -// ------------------------------------------------------------------------------------------------ -// Parse and validate the MD5 header -void MD5Parser::ParseHeader() { - // parse and validate the file version - SkipSpaces(); - if (!TokenMatch(buffer, "MD5Version", 10)) { - ReportError("Invalid MD5 file: MD5Version tag has not been found"); - } - SkipSpaces(); - unsigned int iVer = ::strtoul10(buffer, (const char **)&buffer); - if (10 != iVer) { - ReportError("MD5 version tag is unknown (10 is expected)"); - } - SkipLine(); - - // print the command line options to the console - // FIX: can break the log length limit, so we need to be careful - char *sz = buffer; - while (!IsLineEnd(*buffer++)) - ; - ASSIMP_LOG_INFO(std::string(sz, std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer - sz)))); - SkipSpacesAndLineEnd(); -} - -// ------------------------------------------------------------------------------------------------ -// Recursive MD5 parsing function -bool MD5Parser::ParseSection(Section &out) { - // store the current line number for use in error messages - out.iLineNumber = lineNumber; - - // first parse the name of the section - char *sz = buffer; - while (!IsSpaceOrNewLine(*buffer)) - buffer++; - out.mName = std::string(sz, (uintptr_t)(buffer - sz)); - SkipSpaces(); - - bool running = true; - while (running) { - if ('{' == *buffer) { - // it is a normal section so read all lines - buffer++; - bool run = true; - while (run) { - if (!SkipSpacesAndLineEnd()) { - return false; // seems this was the last section - } - if ('}' == *buffer) { - buffer++; - break; - } - - out.mElements.push_back(Element()); - Element &elem = out.mElements.back(); - - elem.iLineNumber = lineNumber; - elem.szStart = buffer; - - // terminate the line with zero - while (!IsLineEnd(*buffer)) - buffer++; - if (*buffer) { - ++lineNumber; - *buffer++ = '\0'; - } - } - break; - } else if (!IsSpaceOrNewLine(*buffer)) { - // it is an element at global scope. Parse its value and go on - sz = buffer; - while (!IsSpaceOrNewLine(*buffer++)) - ; - out.mGlobalValue = std::string(sz, (uintptr_t)(buffer - sz)); - continue; - } - break; - } - return SkipSpacesAndLineEnd(); -} - -// ------------------------------------------------------------------------------------------------ -// Some dirty macros just because they're so funny and easy to debug - -// skip all spaces ... handle EOL correctly -#define AI_MD5_SKIP_SPACES() \ - if (!SkipSpaces(&sz)) \ - MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber); - -// read a triple float in brackets: (1.0 1.0 1.0) -#define AI_MD5_READ_TRIPLE(vec) \ - AI_MD5_SKIP_SPACES(); \ - if ('(' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move<float>(sz, (float &)vec.x); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move<float>(sz, (float &)vec.y); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move<float>(sz, (float &)vec.z); \ - AI_MD5_SKIP_SPACES(); \ - if (')' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); - -// parse a string, enclosed in quotation marks or not -#define AI_MD5_PARSE_STRING(out) \ - bool bQuota = (*sz == '\"'); \ - const char *szStart = sz; \ - while (!IsSpaceOrNewLine(*sz)) \ - ++sz; \ - const char *szEnd = sz; \ - if (bQuota) { \ - szStart++; \ - if ('\"' != *(szEnd -= 1)) { \ - MD5Parser::ReportWarning("Expected closing quotation marks in string", \ - elem.iLineNumber); \ - continue; \ - } \ - } \ - out.length = (size_t)(szEnd - szStart); \ - ::memcpy(out.data, szStart, out.length); \ - out.data[out.length] = '\0'; - -// parse a string, enclosed in quotation marks -#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \ - while ('\"' != *sz) \ - ++sz; \ - const char *szStart = ++sz; \ - while ('\"' != *sz) \ - ++sz; \ - const char *szEnd = (sz++); \ - out.length = (ai_uint32)(szEnd - szStart); \ - ::memcpy(out.data, szStart, out.length); \ - out.data[out.length] = '\0'; -// ------------------------------------------------------------------------------------------------ -// .MD5MESH parsing function -MD5MeshParser::MD5MeshParser(SectionList &mSections) { - ASSIMP_LOG_DEBUG("MD5MeshParser begin"); - - // now parse all sections - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { - if ((*iter).mName == "numMeshes") { - mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "numJoints") { - mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "joints") { - // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 ) - for (const auto &elem : (*iter).mElements) { - mJoints.push_back(BoneDesc()); - BoneDesc &desc = mJoints.back(); - - const char *sz = elem.szStart; - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); - AI_MD5_SKIP_SPACES(); - - // negative values, at least -1, is allowed here - desc.mParentIndex = (int)strtol10(sz, &sz); - - AI_MD5_READ_TRIPLE(desc.mPositionXYZ); - AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there - } - } else if ((*iter).mName == "mesh") { - mMeshes.push_back(MeshDesc()); - MeshDesc &desc = mMeshes.back(); - - for (const auto &elem : (*iter).mElements) { - const char *sz = elem.szStart; - - // shader attribute - if (TokenMatch(sz, "shader", 6)) { - AI_MD5_SKIP_SPACES(); - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader); - } - // numverts attribute - else if (TokenMatch(sz, "numverts", 8)) { - AI_MD5_SKIP_SPACES(); - desc.mVertices.resize(strtoul10(sz)); - } - // numtris attribute - else if (TokenMatch(sz, "numtris", 7)) { - AI_MD5_SKIP_SPACES(); - desc.mFaces.resize(strtoul10(sz)); - } - // numweights attribute - else if (TokenMatch(sz, "numweights", 10)) { - AI_MD5_SKIP_SPACES(); - desc.mWeights.resize(strtoul10(sz)); - } - // vert attribute - // "vert 0 ( 0.394531 0.513672 ) 0 1" - else if (TokenMatch(sz, "vert", 4)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = ::strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); - if (idx >= desc.mVertices.size()) - desc.mVertices.resize(idx + 1); - - VertexDesc &vert = desc.mVertices[idx]; - if ('(' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); - AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.x); - AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.y); - AI_MD5_SKIP_SPACES(); - if (')' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); - AI_MD5_SKIP_SPACES(); - vert.mFirstWeight = ::strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); - vert.mNumWeights = ::strtoul10(sz, &sz); - } - // tri attribute - // "tri 0 15 13 12" - else if (TokenMatch(sz, "tri", 3)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtoul10(sz, &sz); - if (idx >= desc.mFaces.size()) - desc.mFaces.resize(idx + 1); - - aiFace &face = desc.mFaces[idx]; - face.mIndices = new unsigned int[face.mNumIndices = 3]; - for (unsigned int i = 0; i < 3; ++i) { - AI_MD5_SKIP_SPACES(); - face.mIndices[i] = strtoul10(sz, &sz); - } - } - // weight attribute - // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )" - else if (TokenMatch(sz, "weight", 6)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); - if (idx >= desc.mWeights.size()) - desc.mWeights.resize(idx + 1); - - WeightDesc &weight = desc.mWeights[idx]; - weight.mBone = strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move<float>(sz, weight.mWeight); - AI_MD5_READ_TRIPLE(weight.vOffsetPosition); - } - } - } - } - ASSIMP_LOG_DEBUG("MD5MeshParser end"); -} - -// ------------------------------------------------------------------------------------------------ -// .MD5ANIM parsing function -MD5AnimParser::MD5AnimParser(SectionList &mSections) { - ASSIMP_LOG_DEBUG("MD5AnimParser begin"); - - fFrameRate = 24.0f; - mNumAnimatedComponents = UINT_MAX; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { - if ((*iter).mName == "hierarchy") { - // "sheath" 0 63 6 - for (const auto &elem : (*iter).mElements) { - mAnimatedBones.push_back(AnimBoneDesc()); - AnimBoneDesc &desc = mAnimatedBones.back(); - - const char *sz = elem.szStart; - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); - AI_MD5_SKIP_SPACES(); - - // parent index - negative values are allowed (at least -1) - desc.mParentIndex = ::strtol10(sz, &sz); - - // flags (highest is 2^6-1) - AI_MD5_SKIP_SPACES(); - if (63 < (desc.iFlags = ::strtoul10(sz, &sz))) { - MD5Parser::ReportWarning("Invalid flag combination in hierarchy section", elem.iLineNumber); - } - AI_MD5_SKIP_SPACES(); - - // index of the first animation keyframe component for this joint - desc.iFirstKeyIndex = ::strtoul10(sz, &sz); - } - } else if ((*iter).mName == "baseframe") { - // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 ) - for (const auto &elem : (*iter).mElements) { - const char *sz = elem.szStart; - - mBaseFrames.push_back(BaseFrameDesc()); - BaseFrameDesc &desc = mBaseFrames.back(); - - AI_MD5_READ_TRIPLE(desc.vPositionXYZ); - AI_MD5_READ_TRIPLE(desc.vRotationQuat); - } - } else if ((*iter).mName == "frame") { - if (!(*iter).mGlobalValue.length()) { - MD5Parser::ReportWarning("A frame section must have a frame index", (*iter).iLineNumber); - continue; - } - - mFrames.push_back(FrameDesc()); - FrameDesc &desc = mFrames.back(); - desc.iIndex = strtoul10((*iter).mGlobalValue.c_str()); - - // we do already know how much storage we will presumably need - if (UINT_MAX != mNumAnimatedComponents) { - desc.mValues.reserve(mNumAnimatedComponents); - } - - // now read all elements (continuous list of floats) - for (const auto &elem : (*iter).mElements) { - const char *sz = elem.szStart; - while (SkipSpacesAndLineEnd(&sz)) { - float f; - sz = fast_atoreal_move<float>(sz, f); - desc.mValues.push_back(f); - } - } - } else if ((*iter).mName == "numFrames") { - mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "numJoints") { - const unsigned int num = strtoul10((*iter).mGlobalValue.c_str()); - mAnimatedBones.reserve(num); - - // try to guess the number of animated components if that element is not given - if (UINT_MAX == mNumAnimatedComponents) { - mNumAnimatedComponents = num * 6; - } - } else if ((*iter).mName == "numAnimatedComponents") { - mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "frameRate") { - fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate); - } - } - ASSIMP_LOG_DEBUG("MD5AnimParser end"); -} - -// ------------------------------------------------------------------------------------------------ -// .MD5CAMERA parsing function -MD5CameraParser::MD5CameraParser(SectionList &mSections) { - ASSIMP_LOG_DEBUG("MD5CameraParser begin"); - fFrameRate = 24.0f; - - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { - if ((*iter).mName == "numFrames") { - frames.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "frameRate") { - fFrameRate = fast_atof((*iter).mGlobalValue.c_str()); - } else if ((*iter).mName == "numCuts") { - cuts.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } else if ((*iter).mName == "cuts") { - for (const auto &elem : (*iter).mElements) { - cuts.push_back(strtoul10(elem.szStart) + 1); - } - } else if ((*iter).mName == "camera") { - for (const auto &elem : (*iter).mElements) { - const char *sz = elem.szStart; - - frames.push_back(CameraAnimFrameDesc()); - CameraAnimFrameDesc &cur = frames.back(); - AI_MD5_READ_TRIPLE(cur.vPositionXYZ); - AI_MD5_READ_TRIPLE(cur.vRotationQuat); - AI_MD5_SKIP_SPACES(); - cur.fFOV = fast_atof(sz); - } - } - } - ASSIMP_LOG_DEBUG("MD5CameraParser end"); -} diff --git a/libs/assimp/code/AssetLib/MD5/MD5Parser.h b/libs/assimp/code/AssetLib/MD5/MD5Parser.h deleted file mode 100644 index 3108655..0000000 --- a/libs/assimp/code/AssetLib/MD5/MD5Parser.h +++ /dev/null @@ -1,467 +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 MD5Parser.h - * @brief Definition of the .MD5 parser class. - * http://www.modwiki.net/wiki/MD5_(file_format) - */ -#ifndef AI_MD5PARSER_H_INCLUDED -#define AI_MD5PARSER_H_INCLUDED - -#include <assimp/types.h> -#include <assimp/ParsingUtils.h> -#include <vector> -#include <stdint.h> - -struct aiFace; - -namespace Assimp { -namespace MD5 { - -// --------------------------------------------------------------------------- -/** Represents a single element in a MD5 file - * - * Elements are always contained in sections. -*/ -struct Element -{ - //! Points to the starting point of the element - //! Whitespace at the beginning and at the end have been removed, - //! Elements are terminated with \0 - char* szStart; - - //! Original line number (can be used in error messages - //! if a parsing error occurs) - unsigned int iLineNumber; -}; - -typedef std::vector< Element > ElementList; - -// --------------------------------------------------------------------------- -/** Represents a section of a MD5 file (such as the mesh or the joints section) - * - * A section is always enclosed in { and } brackets. -*/ -struct Section -{ - //! Original line number (can be used in error messages - //! if a parsing error occurs) - unsigned int iLineNumber; - - //! List of all elements which have been parsed in this section. - ElementList mElements; - - //! Name of the section - std::string mName; - - //! For global elements: the value of the element as string - //! Iif !length() the section is not a global element - std::string mGlobalValue; -}; - -typedef std::vector< Section> SectionList; - -// --------------------------------------------------------------------------- -/** Basic information about a joint -*/ -struct BaseJointDescription -{ - //! Name of the bone - aiString mName; - - //! Parent index of the bone - int mParentIndex; -}; - -// --------------------------------------------------------------------------- -/** Represents a bone (joint) descriptor in a MD5Mesh file -*/ -struct BoneDesc : BaseJointDescription -{ - //! Absolute position of the bone - aiVector3D mPositionXYZ; - - //! Absolute rotation of the bone - aiVector3D mRotationQuat; - aiQuaternion mRotationQuatConverted; - - //! Absolute transformation of the bone - //! (temporary) - aiMatrix4x4 mTransform; - - //! Inverse transformation of the bone - //! (temporary) - aiMatrix4x4 mInvTransform; - - //! Internal - unsigned int mMap; -}; - -typedef std::vector< BoneDesc > BoneList; - -// --------------------------------------------------------------------------- -/** Represents a bone (joint) descriptor in a MD5Anim file -*/ -struct AnimBoneDesc : BaseJointDescription -{ - //! Flags (AI_MD5_ANIMATION_FLAG_xxx) - unsigned int iFlags; - - //! Index of the first key that corresponds to this anim bone - unsigned int iFirstKeyIndex; -}; - -typedef std::vector< AnimBoneDesc > AnimBoneList; - - -// --------------------------------------------------------------------------- -/** Represents a base frame descriptor in a MD5Anim file -*/ -struct BaseFrameDesc -{ - aiVector3D vPositionXYZ; - aiVector3D vRotationQuat; -}; - -typedef std::vector< BaseFrameDesc > BaseFrameList; - -// --------------------------------------------------------------------------- -/** Represents a camera animation frame in a MDCamera file -*/ -struct CameraAnimFrameDesc : BaseFrameDesc -{ - float fFOV; -}; - -typedef std::vector< CameraAnimFrameDesc > CameraFrameList; - -// --------------------------------------------------------------------------- -/** Represents a frame descriptor in a MD5Anim file -*/ -struct FrameDesc -{ - //! Index of the frame - unsigned int iIndex; - - //! Animation keyframes - a large blob of data at first - std::vector< float > mValues; -}; - -typedef std::vector< FrameDesc > FrameList; - -// --------------------------------------------------------------------------- -/** Represents a vertex descriptor in a MD5 file -*/ -struct VertexDesc { - VertexDesc() AI_NO_EXCEPT - : mFirstWeight(0) - , mNumWeights(0) { - // empty - } - - //! UV coordinate of the vertex - aiVector2D mUV; - - //! Index of the first weight of the vertex in - //! the vertex weight list - unsigned int mFirstWeight; - - //! Number of weights assigned to this vertex - unsigned int mNumWeights; -}; - -typedef std::vector< VertexDesc > VertexList; - -// --------------------------------------------------------------------------- -/** Represents a vertex weight descriptor in a MD5 file -*/ -struct WeightDesc -{ - //! Index of the bone to which this weight refers - unsigned int mBone; - - //! The weight value - float mWeight; - - //! The offset position of this weight - // ! (in the coordinate system defined by the parent bone) - aiVector3D vOffsetPosition; -}; - -typedef std::vector< WeightDesc > WeightList; -typedef std::vector< aiFace > FaceList; - -// --------------------------------------------------------------------------- -/** Represents a mesh in a MD5 file -*/ -struct MeshDesc -{ - //! Weights of the mesh - WeightList mWeights; - - //! Vertices of the mesh - VertexList mVertices; - - //! Faces of the mesh - FaceList mFaces; - - //! Name of the shader (=texture) to be assigned to the mesh - aiString mShader; -}; - -typedef std::vector< MeshDesc > MeshList; - -// --------------------------------------------------------------------------- -// Convert a quaternion to its usual representation -inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) { - - out.x = in.x; - out.y = in.y; - out.z = in.z; - - const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z); - - if (t < 0.0f) - out.w = 0.0f; - else out.w = std::sqrt (t); - - // Assimp convention. - out.w *= -1.f; -} - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 mesh file -*/ -class MD5MeshParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5MeshParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - explicit MD5MeshParser(SectionList& mSections); - - //! List of all meshes - MeshList mMeshes; - - //! List of all joints - BoneList mJoints; -}; - -// remove this flag if you need to the bounding box data -#define AI_MD5_PARSE_NO_BOUNDS - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 animation file -*/ -class MD5AnimParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5AnimParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - explicit MD5AnimParser(SectionList& mSections); - - - //! Output frame rate - float fFrameRate; - - //! List of animation bones - AnimBoneList mAnimatedBones; - - //! List of base frames - BaseFrameList mBaseFrames; - - //! List of animation frames - FrameList mFrames; - - //! Number of animated components - unsigned int mNumAnimatedComponents; -}; - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 camera animation file -*/ -class MD5CameraParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5CameraParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - explicit MD5CameraParser(SectionList& mSections); - - - //! Output frame rate - float fFrameRate; - - //! List of cuts - std::vector<unsigned int> cuts; - - //! Frames - CameraFrameList frames; -}; - -// --------------------------------------------------------------------------- -/** Parses the block structure of MD5MESH and MD5ANIM files (but does no - * further processing) -*/ -class MD5Parser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5Parser instance from an existing buffer. - * - * @param buffer File buffer - * @param fileSize Length of the file in bytes (excluding a terminal 0) - */ - MD5Parser(char* buffer, unsigned int fileSize); - - - // ------------------------------------------------------------------- - /** Report a specific error message and throw an exception - * @param error Error message to be reported - * @param line Index of the line where the error occurred - */ - AI_WONT_RETURN static void ReportError (const char* error, unsigned int line) AI_WONT_RETURN_SUFFIX; - - // ------------------------------------------------------------------- - /** Report a specific warning - * @param warn Warn message to be reported - * @param line Index of the line where the error occurred - */ - static void ReportWarning (const char* warn, unsigned int line); - - - void ReportError (const char* error) { - return ReportError(error, lineNumber); - } - - void ReportWarning (const char* warn) { - return ReportWarning(warn, lineNumber); - } - -public: - - //! List of all sections which have been read - SectionList mSections; - -private: - - // ------------------------------------------------------------------- - /** Parses a file section. The current file pointer must be outside - * of a section. - * @param out Receives the section data - * @return true if the end of the file has been reached - * @throws ImportErrorException if an error occurs - */ - bool ParseSection(Section& out); - - // ------------------------------------------------------------------- - /** Parses the file header - * @throws ImportErrorException if an error occurs - */ - void ParseHeader(); - - - // override these functions to make sure the line counter gets incremented - // ------------------------------------------------------------------- - bool SkipLine( const char* in, const char** out) - { - ++lineNumber; - return Assimp::SkipLine(in,out); - } - // ------------------------------------------------------------------- - bool SkipLine( ) - { - return SkipLine(buffer,(const char**)&buffer); - } - // ------------------------------------------------------------------- - bool SkipSpacesAndLineEnd( const char* in, const char** out) - { - bool bHad = false; - bool running = true; - while (running) { - if( *in == '\r' || *in == '\n') { - // we open files in binary mode, so there could be \r\n sequences ... - if (!bHad) { - bHad = true; - ++lineNumber; - } - } - else if (*in == '\t' || *in == ' ')bHad = false; - else break; - in++; - } - *out = in; - return *in != '\0'; - } - // ------------------------------------------------------------------- - bool SkipSpacesAndLineEnd( ) - { - return SkipSpacesAndLineEnd(buffer,(const char**)&buffer); - } - // ------------------------------------------------------------------- - bool SkipSpaces( ) - { - return Assimp::SkipSpaces((const char**)&buffer); - } - - char* buffer; - unsigned int fileSize; - unsigned int lineNumber; -}; -}} - -#endif // AI_MD5PARSER_H_INCLUDED |