diff options
Diffstat (limited to 'libs/assimp/code/AssetLib/SMD')
-rw-r--r-- | libs/assimp/code/AssetLib/SMD/SMDLoader.cpp | 1098 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/SMD/SMDLoader.h | 395 |
2 files changed, 0 insertions, 1493 deletions
diff --git a/libs/assimp/code/AssetLib/SMD/SMDLoader.cpp b/libs/assimp/code/AssetLib/SMD/SMDLoader.cpp deleted file mode 100644 index 46fd968..0000000 --- a/libs/assimp/code/AssetLib/SMD/SMDLoader.cpp +++ /dev/null @@ -1,1098 +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 SMDLoader.cpp - * @brief Implementation of the SMD importer class - */ - - -#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER - -#include <assimp/fast_atof.h> -#include <assimp/SkeletonMeshBuilder.h> -#include <assimp/Importer.hpp> -#include <assimp/IOSystem.hpp> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/importerdesc.h> -#include <memory> -#include <assimp/DefaultIOSystem.h> -#include <tuple> - -// internal headers -#include "SMDLoader.h" - -#ifndef _MSC_VER -#define strtok_s strtok_r -#endif - -using namespace Assimp; - -static const aiImporterDesc desc = { - "Valve SMD Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "smd vta" -}; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -SMDImporter::SMDImporter() : - configFrameID(), - mBuffer(), - pScene( nullptr ), - iFileSize( 0 ), - iSmallestFrame( INT_MAX ), - dLengthOfAnim( 0.0 ), - bHasUVs(false ), - iLineNumber((unsigned int)-1) { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -SMDImporter::~SMDImporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool SMDImporter::CanRead( const std::string& filename, IOSystem* /*pIOHandler*/, bool) const { - return SimpleExtensionCheck(filename, "smd", "vta"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all supported file extensions -const aiImporterDesc* SMDImporter::GetInfo () const { - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void SMDImporter::SetupProperties(const Importer* pImp) { - // The - // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_SMD_KEYFRAME,-1); - if(static_cast<unsigned int>(-1) == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } - - bLoadAnimationList = pImp->GetPropertyBool(AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST, true); - noSkeletonMesh = pImp->GetPropertyBool(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, false); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void SMDImporter::InternReadFile( const std::string& pFile, aiScene* scene, IOSystem* pIOHandler) { - this->pScene = scene; - ReadSmd(pFile, pIOHandler); - - // If there are no triangles it seems to be an animation SMD, - // containing only the animation skeleton. - if (asTriangles.empty()) { - if (asBones.empty()) { - throw DeadlyImportError("SMD: No triangles and no bones have " - "been found in the file. This file seems to be invalid."); - } - - // Set the flag in the scene structure which indicates - // that there is nothing than an animation skeleton - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - if (!asBones.empty()) { - // Check whether all bones have been initialized - for (std::vector<SMD::Bone>::const_iterator - i = asBones.begin(); - i != asBones.end();++i) { - if (!(*i).mName.length()) { - ASSIMP_LOG_WARN("SMD: Not all bones have been initialized"); - break; - } - } - - // now fix invalid time values and make sure the animation starts at frame 0 - FixTimeValues(); - } - - // build output nodes (bones are added as empty dummy nodes) - CreateOutputNodes(); - - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - // create output meshes - CreateOutputMeshes(); - - // build an output material list - CreateOutputMaterials(); - - // use root node that renders all meshes - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - pScene->mRootNode->mMeshes[i] = i; - } - } - - // build the output animation - CreateOutputAnimations(pFile, pIOHandler); - - if ((pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) && !noSkeletonMesh) { - SkeletonMeshBuilder skeleton(pScene); - } -} - -// ------------------------------------------------------------------------------------------------ -// Write an error message with line number to the log file -void SMDImporter::LogErrorNoThrow(const char* msg) { - const size_t _BufferSize = 1024; - char szTemp[_BufferSize]; - ai_snprintf(szTemp,_BufferSize,"Line %u: %s",iLineNumber,msg); - DefaultLogger::get()->error(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -// Write a warning with line number to the log file -void SMDImporter::LogWarning(const char* msg) { - const size_t _BufferSize = 1024; - char szTemp[_BufferSize]; - ai_assert(strlen(msg) < 1000); - ai_snprintf(szTemp,_BufferSize,"Line %u: %s",iLineNumber,msg); - ASSIMP_LOG_WARN(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -// Fix invalid time values in the file -void SMDImporter::FixTimeValues() { - double dDelta = (double)iSmallestFrame; - double dMax = 0.0f; - for (std::vector<SMD::Bone>::iterator - iBone = asBones.begin(); - iBone != asBones.end();++iBone) { - for (std::vector<SMD::Bone::Animation::MatrixKey>::iterator - iKey = (*iBone).sAnim.asKeys.begin(); - iKey != (*iBone).sAnim.asKeys.end();++iKey) { - (*iKey).dTime -= dDelta; - dMax = std::max(dMax, (*iKey).dTime); - } - } - dLengthOfAnim = dMax; -} - -// ------------------------------------------------------------------------------------------------ -// create output meshes -void SMDImporter::CreateOutputMeshes() { - if (aszTextures.empty()) { - aszTextures.push_back(std::string()); - } - - // we need to sort all faces by their material index - // in opposition to other loaders we can be sure that each - // material is at least used once. - pScene->mNumMeshes = (unsigned int) aszTextures.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - - typedef std::vector<unsigned int> FaceList; - FaceList* aaiFaces = new FaceList[pScene->mNumMeshes]; - - // approximate the space that will be required - unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes; - iNum += iNum >> 1; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - aaiFaces[i].reserve(iNum); - } - - // collect all faces - iNum = 0; - for (std::vector<SMD::Face>::const_iterator - iFace = asTriangles.begin(); - iFace != asTriangles.end();++iFace,++iNum) { - if (UINT_MAX == (*iFace).iTexture) { - aaiFaces[(*iFace).iTexture].push_back( 0 ); - } else if ((*iFace).iTexture >= aszTextures.size()) { - ASSIMP_LOG_INFO("[SMD/VTA] Material index overflow in face"); - aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1); - } else { - aaiFaces[(*iFace).iTexture].push_back(iNum); - } - } - - // now create the output meshes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh(); - ai_assert(!aaiFaces[i].empty()); // should not be empty ... - - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pcMesh->mNumVertices = (unsigned int)aaiFaces[i].size()*3; - pcMesh->mNumFaces = (unsigned int)aaiFaces[i].size(); - pcMesh->mMaterialIndex = i; - - // storage for bones - typedef std::pair<unsigned int,float> TempWeightListEntry; - typedef std::vector< TempWeightListEntry > TempBoneWeightList; - - TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()](); - - // try to reserve enough memory without wasting too much - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { - aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size()); - } - - // allocate storage - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - - aiVector3D* pcUVs = nullptr; - if (bHasUVs) { - pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - } - - iNum = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { - pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; - pcMesh->mFaces[iFace].mNumIndices = 3; - - // fill the vertices - unsigned int iSrcFace = aaiFaces[i][iFace]; - SMD::Face& face = asTriangles[iSrcFace]; - - *pcVerts++ = face.avVertices[0].pos; - *pcVerts++ = face.avVertices[1].pos; - *pcVerts++ = face.avVertices[2].pos; - - // fill the normals - *pcNormals++ = face.avVertices[0].nor; - *pcNormals++ = face.avVertices[1].nor; - *pcNormals++ = face.avVertices[2].nor; - - // fill the texture coordinates - if (pcUVs) { - *pcUVs++ = face.avVertices[0].uv; - *pcUVs++ = face.avVertices[1].uv; - *pcUVs++ = face.avVertices[2].uv; - } - - for (unsigned int iVert = 0; iVert < 3;++iVert) { - float fSum = 0.0f; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { - TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - - // FIX: The second check is here just to make sure we won't - // assign more than one weight to a single vertex index - if (pairval.first >= asBones.size() || pairval.first == face.avVertices[iVert].iParentNode) { - ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " - "The bone index will be ignored, the weight will be assigned " - "to the vertex' parent node"); - continue; - } - aaiBones[pairval.first].push_back(TempWeightListEntry(iNum,pairval.second)); - fSum += pairval.second; - } - // ****************************************************************** - // If the sum of all vertex weights is not 1.0 we must assign - // the rest to the vertex' parent node. Well, at least the doc says - // we should ... - // FIX: We use 0.975 as limit, floating-point inaccuracies seem to - // be very strong in some SMD exporters. Furthermore it is possible - // that the parent of a vertex is 0xffffffff (if the corresponding - // entry in the file was unreadable) - // ****************************************************************** - if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX) { - if (face.avVertices[iVert].iParentNode >= asBones.size()) { - ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " - "The index of the vertex parent bone is invalid. " - "The remaining weights will be normalized to 1.0"); - - if (fSum) { - fSum = 1 / fSum; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { - TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - if (pairval.first >= asBones.size()) { - continue; - } - aaiBones[pairval.first].back().second *= fSum; - } - } - } else { - aaiBones[face.avVertices[iVert].iParentNode].push_back( - TempWeightListEntry(iNum,1.0f-fSum)); - } - } - pcMesh->mFaces[iFace].mIndices[iVert] = iNum++; - } - } - - // now build all bones of the mesh - iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { - if (!aaiBones[iBone].empty())++iNum; - } - - if (iNum) { - pcMesh->mNumBones = iNum; - pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; - iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { - if (aaiBones[iBone].empty()) { - continue; - } - aiBone*& bone = pcMesh->mBones[iNum] = new aiBone(); - - bone->mNumWeights = (unsigned int)aaiBones[iBone].size(); - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - bone->mOffsetMatrix = asBones[iBone].mOffsetMatrix; - bone->mName.Set( asBones[iBone].mName ); - - asBones[iBone].bIsUsed = true; - - for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) { - bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first; - bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second; - } - ++iNum; - } - } - delete[] aaiBones; - } - delete[] aaiFaces; -} - -// ------------------------------------------------------------------------------------------------ -// add bone child nodes -void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) { - ai_assert( nullptr != pcNode ); - ai_assert( 0 == pcNode->mNumChildren ); - ai_assert( nullptr == pcNode->mChildren); - - // first count ... - for (unsigned int i = 0; i < asBones.size();++i) { - SMD::Bone& bone = asBones[i]; - if (bone.iParent == iParent) { - ++pcNode->mNumChildren; - } - } - - // now allocate the output array - pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; - - // and fill all subnodes - unsigned int qq( 0 ); - for (unsigned int i = 0; i < asBones.size();++i) { - SMD::Bone& bone = asBones[i]; - if (bone.iParent != iParent) { - continue; - } - - aiNode* pc = pcNode->mChildren[qq++] = new aiNode(); - pc->mName.Set(bone.mName); - - // store the local transformation matrix of the bind pose - if (bone.sAnim.asKeys.size()) { - pc->mTransformation = bone.sAnim.asKeys[0].matrix; - } - - if (bone.iParent == static_cast<uint32_t>(-1)) { - bone.mOffsetMatrix = pc->mTransformation; - } else { - bone.mOffsetMatrix = asBones[bone.iParent].mOffsetMatrix * pc->mTransformation; - } - - pc->mParent = pcNode; - - // add children to this node, too - AddBoneChildren(pc,i); - } -} - -// ------------------------------------------------------------------------------------------------ -// create output nodes -void SMDImporter::CreateOutputNodes() { - pScene->mRootNode = new aiNode(); - - // now add all bones as dummy sub nodes to the graph - AddBoneChildren(pScene->mRootNode,(uint32_t)-1); - for (auto &bone : asBones) { - bone.mOffsetMatrix.Inverse(); - } - - // if we have only one bone we can even remove the root node - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && 1 == pScene->mRootNode->mNumChildren) { - aiNode* pcOldRoot = pScene->mRootNode; - pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = nullptr; - delete pcOldRoot; - - pScene->mRootNode->mParent = nullptr; - } - else - { - ::strcpy(pScene->mRootNode->mName.data, "<SMD_root>"); - pScene->mRootNode->mName.length = 10; - } -} - -// ------------------------------------------------------------------------------------------------ -// create output animations -void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler) { - std::vector<std::tuple<std::string, std::string>> animFileList; - - if (bLoadAnimationList) { - GetAnimationFileList(pFile, pIOHandler, animFileList); - } - int animCount = static_cast<int>( animFileList.size() + 1u ); - pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[animCount]; - memset(pScene->mAnimations, 0, sizeof(aiAnimation*)*animCount); - CreateOutputAnimation(0, ""); - - for (auto &animFile : animFileList) { - ReadSmd(std::get<1>(animFile), pIOHandler); - if (asBones.empty()) { - continue; - } - - FixTimeValues(); - CreateOutputAnimation(pScene->mNumAnimations++, std::get<0>(animFile)); - } -} - -void SMDImporter::CreateOutputAnimation(int index, const std::string &name) { - aiAnimation*& anim = pScene->mAnimations[index] = new aiAnimation(); - - if (name.length()) { - anim->mName.Set(name.c_str()); - } - anim->mDuration = dLengthOfAnim; - anim->mNumChannels = static_cast<unsigned int>( asBones.size() ); - anim->mTicksPerSecond = 25.0; // FIXME: is this correct? - - aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - - // now build valid keys - unsigned int a = 0; - for (std::vector<SMD::Bone>::const_iterator i = asBones.begin(); i != asBones.end(); ++i) { - aiNodeAnim* p = pp[a] = new aiNodeAnim(); - - // copy the name of the bone - p->mNodeName.Set(i->mName); - - p->mNumRotationKeys = (unsigned int)(*i).sAnim.asKeys.size(); - if (p->mNumRotationKeys){ - p->mNumPositionKeys = p->mNumRotationKeys; - aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys]; - aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys]; - - for (std::vector<SMD::Bone::Animation::MatrixKey>::const_iterator - qq = (*i).sAnim.asKeys.begin(); - qq != (*i).sAnim.asKeys.end(); ++qq) { - pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; - - // compute the rotation quaternion from the euler angles - // aiQuaternion: The order of the parameters is yzx? - pRotKeys->mValue = aiQuaternion((*qq).vRot.y, (*qq).vRot.z, (*qq).vRot.x); - pVecKeys->mValue = (*qq).vPos; - - ++pVecKeys; ++pRotKeys; - } - } - ++a; - - // there are no scaling keys ... - } -} - -void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector<std::tuple<std::string, std::string>>& outList) { - auto base = DefaultIOSystem::absolutePath(pFile); - auto name = DefaultIOSystem::completeBaseName(pFile); - auto path = base + "/" + name + "_animation.txt"; - - std::unique_ptr<IOStream> file(pIOHandler->Open(path.c_str(), "rb")); - if (file.get() == nullptr) { - return; - } - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector<char> buf; - size_t fileSize = file->FileSize(); - buf.resize(fileSize + 1); - TextFileToBuffer(file.get(), buf); - - /* - *_animation.txt format: - name path - idle idle.smd - jump anim/jump.smd - walk.smd - ... - */ - std::string animName, animPath; - char *tok1, *tok2; - char *context1, *context2; - - tok1 = strtok_s(&buf[0], "\r\n", &context1); - while (tok1 != nullptr) { - tok2 = strtok_s(tok1, " \t", &context2); - if (tok2) { - char *p = tok2; - tok2 = strtok_s(nullptr, " \t", &context2); - if (tok2) { - animPath = tok2; - animName = p; - } else { - // No name - animPath = p; - animName = DefaultIOSystem::completeBaseName(animPath); - } - outList.push_back(std::make_tuple(animName, base + "/" + animPath)); - } - tok1 = strtok_s(nullptr, "\r\n", &context1); - } -} - -// ------------------------------------------------------------------------------------------------ -// create output materials -void SMDImporter::CreateOutputMaterials() { - ai_assert( nullptr != pScene ); - - pScene->mNumMaterials = (unsigned int)aszTextures.size(); - pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)]; - - for (unsigned int iMat = 0; iMat < pScene->mNumMaterials; ++iMat) { - aiMaterial* pcMat = new aiMaterial(); - ai_assert( nullptr != pcMat ); - pScene->mMaterials[iMat] = pcMat; - - aiString szName; - szName.length = (size_t)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat); - pcMat->AddProperty(&szName,AI_MATKEY_NAME); - - if (aszTextures[iMat].length()) - { - ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1); - szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() ); - pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - } - - // create a default material if necessary - if (0 == pScene->mNumMaterials) { - pScene->mNumMaterials = 1; - - aiMaterial* pcHelper = new aiMaterial(); - pScene->mMaterials[0] = pcHelper; - - int iMode = static_cast<int>(aiShadingMode_Gouraud); - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.7f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - } -} - -// ------------------------------------------------------------------------------------------------ -// Parse the file -void SMDImporter::ParseFile() { - const char* szCurrent = &mBuffer[0]; - - // read line per line ... - for ( ;; ) { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { - break; - } - - // "version <n> \n", <n> should be 1 for hl and hl2 SMD files - if (TokenMatch(szCurrent,"version",7)) { - if(!SkipSpaces(szCurrent,&szCurrent)) break; - if (1 != strtoul10(szCurrent,&szCurrent)) { - ASSIMP_LOG_WARN("SMD.version is not 1. This " - "file format is not known. Continuing happily ..."); - } - continue; - } - // "nodes\n" - Starts the node section - if (TokenMatch(szCurrent,"nodes",5)) { - ParseNodesSection(szCurrent,&szCurrent); - continue; - } - // "triangles\n" - Starts the triangle section - if (TokenMatch(szCurrent,"triangles",9)) { - ParseTrianglesSection(szCurrent,&szCurrent); - continue; - } - // "vertexanimation\n" - Starts the vertex animation section - if (TokenMatch(szCurrent,"vertexanimation",15)) { - bHasUVs = false; - ParseVASection(szCurrent,&szCurrent); - continue; - } - // "skeleton\n" - Starts the skeleton section - if (TokenMatch(szCurrent,"skeleton",8)) { - ParseSkeletonSection(szCurrent,&szCurrent); - continue; - } - SkipLine(szCurrent,&szCurrent); - } -} - -void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) { - std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (file.get() == nullptr) { - throw DeadlyImportError("Failed to open SMD/VTA file ", pFile, "."); - } - - iFileSize = (unsigned int)file->FileSize(); - - // Allocate storage and copy the contents of the file to a memory buffer - mBuffer.resize(iFileSize + 1); - TextFileToBuffer(file.get(), mBuffer); - - iSmallestFrame = INT_MAX; - bHasUVs = true; - iLineNumber = 1; - - // Reserve enough space for ... hm ... 10 textures - aszTextures.reserve(10); - - // Reserve enough space for ... hm ... 1000 triangles - asTriangles.reserve(1000); - - // Reserve enough space for ... hm ... 20 bones - asBones.reserve(20); - - aszTextures.clear(); - asTriangles.clear(); - asBones.clear(); - - // parse the file ... - ParseFile(); -} - -// ------------------------------------------------------------------------------------------------ -unsigned int SMDImporter::GetTextureIndex(const std::string& filename) { - unsigned int iIndex = 0; - for (std::vector<std::string>::const_iterator - i = aszTextures.begin(); - i != aszTextures.end();++i,++iIndex) { - // case-insensitive ... it's a path - if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str())) { - return iIndex; - } - } - iIndex = (unsigned int)aszTextures.size(); - aszTextures.push_back(filename); - return iIndex; -} - -// ------------------------------------------------------------------------------------------------ -// Parse the nodes section of the file -void SMDImporter::ParseNodesSection(const char* szCurrent, const char** szCurrentOut) { - for ( ;; ) { - // "end\n" - Ends the nodes section - if (0 == ASSIMP_strincmp(szCurrent,"end",3) && IsSpaceOrNewLine(*(szCurrent+3))) { - szCurrent += 4; - break; - } - ParseNodeInfo(szCurrent,&szCurrent); - } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Parse the triangles section of the file -void SMDImporter::ParseTrianglesSection(const char* szCurrent, const char** szCurrentOut) { - // Parse a triangle, parse another triangle, parse the next triangle ... - // and so on until we reach a token that looks quite similar to "end" - for ( ;; ) { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { - break; - } - - // "end\n" - Ends the triangles section - if (TokenMatch(szCurrent,"end",3)) { - break; - } - ParseTriangle(szCurrent,&szCurrent); - } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} -// ------------------------------------------------------------------------------------------------ -// Parse the vertex animation section of the file -void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOut) { - unsigned int iCurIndex = 0; - for ( ;; ) { - if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { - break; - } - - // "end\n" - Ends the "vertexanimation" section - if (TokenMatch(szCurrent,"end",3)) { - break; - } - - // "time <n>\n" - if (TokenMatch(szCurrent,"time",4)) { - // NOTE: The doc says that time values COULD be negative ... - // NOTE2: this is the shape key -> valve docs - int iTime = 0; - if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime) { - break; - } - SkipLine(szCurrent,&szCurrent); - } else { - if(0 == iCurIndex) { - asTriangles.push_back(SMD::Face()); - } - if (++iCurIndex == 3) { - iCurIndex = 0; - } - ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true); - } - } - - if (iCurIndex != 2 && !asTriangles.empty()) { - // we want to no degenerates, so throw this triangle away - asTriangles.pop_back(); - } - - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Parse the skeleton section of the file -void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCurrentOut) { - int iTime = 0; - for ( ;; ) { - if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { - break; - } - - // "end\n" - Ends the skeleton section - if (TokenMatch(szCurrent,"end",3)) { - break; - } else if (TokenMatch(szCurrent,"time",4)) { - // "time <n>\n" - Specifies the current animation frame - if(!ParseSignedInt(szCurrent,&szCurrent,iTime)) { - break; - } - - iSmallestFrame = std::min(iSmallestFrame,iTime); - SkipLine(szCurrent,&szCurrent); - } else { - ParseSkeletonElement(szCurrent,&szCurrent,iTime); - } - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -#define SMDI_PARSE_RETURN { \ - SkipLine(szCurrent,&szCurrent); \ - *szCurrentOut = szCurrent; \ - return; \ -} -// ------------------------------------------------------------------------------------------------ -// Parse a node line -void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut) { - unsigned int iBone = 0; - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - if ( !ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index"); - SMDI_PARSE_RETURN; - } - // add our bone to the list - if (iBone >= asBones.size()) { - asBones.resize(iBone+1); - } - SMD::Bone& bone = asBones[iBone]; - - bool bQuota = true; - if ('\"' != *szCurrent) { - LogWarning("Bone name is expected to be enclosed in " - "double quotation marks. "); - bQuota = false; - } else { - ++szCurrent; - } - - const char* szEnd = szCurrent; - for ( ;; ) { - if (bQuota && '\"' == *szEnd) { - iBone = (unsigned int)(szEnd - szCurrent); - ++szEnd; - break; - } else if (!bQuota && IsSpaceOrNewLine(*szEnd)) { - iBone = (unsigned int)(szEnd - szCurrent); - break; - } else if (!(*szEnd)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name"); - SMDI_PARSE_RETURN; - } - ++szEnd; - } - bone.mName = std::string(szCurrent,iBone); - szCurrent = szEnd; - - // the only negative bone parent index that could occur is -1 AFAIK - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1"); - SMDI_PARSE_RETURN; - } - - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a skeleton element -void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCurrentOut,int iTime) { - aiVector3D vPos; - aiVector3D vRot; - - unsigned int iBone = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) { - ASSIMP_LOG_ERROR("Unexpected EOF/EOL while parsing bone index"); - SMDI_PARSE_RETURN; - } - if (iBone >= asBones.size()) { - LogErrorNoThrow("Bone index in skeleton section is out of range"); - SMDI_PARSE_RETURN; - } - SMD::Bone& bone = asBones[iBone]; - - bone.sAnim.asKeys.push_back(SMD::Bone::Animation::MatrixKey()); - SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back(); - - key.dTime = (double)iTime; - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z"); - SMDI_PARSE_RETURN; - } - // build the transformation matrix of the key - key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); { - aiMatrix4x4 mTemp; - mTemp.a4 = vPos.x; - mTemp.b4 = vPos.y; - mTemp.c4 = vPos.z; - key.matrix = mTemp * key.matrix; - } - key.vPos = vPos; - key.vRot = vRot; - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a triangle -void SMDImporter::ParseTriangle(const char* szCurrent, const char** szCurrentOut) { - asTriangles.push_back(SMD::Face()); - SMD::Face& face = asTriangles.back(); - - if(!SkipSpaces(szCurrent,&szCurrent)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle"); - return; - } - - // read the texture file name - const char* szLast = szCurrent; - while (!IsSpaceOrNewLine(*++szCurrent)); - - // ... and get the index that belongs to this file name - face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast)); - - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - - // load three vertices - for (unsigned int iVert = 0; iVert < 3;++iVert) { - ParseVertex(szCurrent,&szCurrent, face.avVertices[iVert]); - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a float -bool SMDImporter::ParseFloat(const char* szCurrent, const char** szCurrentOut, float& out) { - if(!SkipSpaces(&szCurrent)) { - return false; - } - - *szCurrentOut = fast_atoreal_move<float>(szCurrent,out); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse an unsigned int -bool SMDImporter::ParseUnsignedInt(const char* szCurrent, const char** szCurrentOut, unsigned int& out) { - if(!SkipSpaces(&szCurrent)) { - return false; - } - - out = strtoul10(szCurrent,szCurrentOut); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a signed int -bool SMDImporter::ParseSignedInt(const char* szCurrent, const char** szCurrentOut, int& out) { - if(!SkipSpaces(&szCurrent)) { - return false; - } - - out = strtol10(szCurrent,szCurrentOut); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a vertex -void SMDImporter::ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection /*= false*/) { - if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) { - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection); - } - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z"); - SMDI_PARSE_RETURN; - } - - if (bVASection) { - SMDI_PARSE_RETURN; - } - - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y"); - SMDI_PARSE_RETURN; - } - - // now read the number of bones affecting this vertex - // all elements from now are fully optional, we don't need them - unsigned int iSize = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize)) { - SMDI_PARSE_RETURN; - } - vertex.aiBoneLinks.resize(iSize,std::pair<unsigned int, float>(0,0.0f)); - - for (std::vector<std::pair<unsigned int, float> >::iterator - i = vertex.aiBoneLinks.begin(); - i != vertex.aiBoneLinks.end();++i) { - if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) { - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) { - SMDI_PARSE_RETURN; - } - } - - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -#endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER diff --git a/libs/assimp/code/AssetLib/SMD/SMDLoader.h b/libs/assimp/code/AssetLib/SMD/SMDLoader.h deleted file mode 100644 index db882a2..0000000 --- a/libs/assimp/code/AssetLib/SMD/SMDLoader.h +++ /dev/null @@ -1,395 +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 SMDLoader.h - * @brief Definition of the Valve SMD file format - */ - -#pragma once -#ifndef AI_SMDLOADER_H_INCLUDED -#define AI_SMDLOADER_H_INCLUDED - -#include <assimp/BaseImporter.h> -#include <assimp/ParsingUtils.h> -#include <assimp/types.h> -#include <assimp/texture.h> -#include <assimp/anim.h> -#include <assimp/material.h> - -#include <vector> - -struct aiNode; - -namespace Assimp { -namespace SMD { - -// --------------------------------------------------------------------------- -/** Data structure for a vertex in a SMD file -*/ -struct Vertex { - Vertex() AI_NO_EXCEPT : iParentNode(UINT_MAX) { - // empty - } - - //! Vertex position, normal and texture coordinate - aiVector3D pos,nor,uv; - - //! Vertex parent node - unsigned int iParentNode; - - //! Links to bones: pair.first is the bone index, - //! pair.second is the vertex weight. - //! WARN: The remaining weight (to reach 1.0f) is assigned - //! to the parent node/bone - std::vector<std::pair<unsigned int, float> > aiBoneLinks; -}; - -// --------------------------------------------------------------------------- -/** Data structure for a face in a SMD file -*/ -struct Face { - Face() AI_NO_EXCEPT : - iTexture(0x0), avVertices{} { - // empty - } - - //! Texture index for the face - unsigned int iTexture; - - //! The three vertices of the face - Vertex avVertices[3]; -}; - -// --------------------------------------------------------------------------- -/** Data structure for a bone in a SMD file -*/ -struct Bone { - //! Default constructor - Bone() AI_NO_EXCEPT : iParent(UINT_MAX), bIsUsed(false) { - // empty - } - - //! Name of the bone - std::string mName; - - //! Parent of the bone - uint32_t iParent; - - //! Animation of the bone - struct Animation { - //! Public default constructor - Animation() AI_NO_EXCEPT : iFirstTimeKey() { - asKeys.reserve(20); - } - - //! Data structure for a matrix key - struct MatrixKey { - //! Matrix at this time - aiMatrix4x4 matrix; - - //! Absolute transformation matrix - aiMatrix4x4 matrixAbsolute; - - //! Position - aiVector3D vPos; - - //! Rotation (euler angles) - aiVector3D vRot; - - //! Current time. may be negative, this - //! will be fixed later - double dTime; - }; - - //! Index of the key with the smallest time value - uint32_t iFirstTimeKey; - - //! Array of matrix keys - std::vector<MatrixKey> asKeys; - - } sAnim; - - //! Offset matrix of the bone - aiMatrix4x4 mOffsetMatrix; - - //! true if the bone is referenced by at least one mesh - bool bIsUsed; -}; - -} //! namespace SMD - -// --------------------------------------------------------------------------- -/** Used to load Half-life 1 and 2 SMD models -*/ -class ASSIMP_API SMDImporter : public BaseImporter { -public: - SMDImporter(); - ~SMDImporter() 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; - - // ------------------------------------------------------------------- - /** 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; - -protected: - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details - */ - const aiImporterDesc* GetInfo () const 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; - - // ------------------------------------------------------------------- - /** Parse the SMD file and create the output scene - */ - void ParseFile(); - void ReadSmd(const std::string &pFile, IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Parse the triangles section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the vertex animation section in VTA files - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseVASection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the nodes section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseNodesSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the skeleton section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse a single triangle in the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives the output cursor position - */ - void ParseTriangle(const char* szCurrent, - const char** szCurrentOut); - - - // ------------------------------------------------------------------- - /** Parse a single vertex in the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives the output cursor position - * \param vertex Vertex to be filled - */ - void ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection = false); - - // ------------------------------------------------------------------- - /** Get the index of a texture. If the texture was not yet known - * it will be added to the internal texture list. - * \param filename Name of the texture - * \return Value texture index - */ - unsigned int GetTextureIndex(const std::string& filename); - - // ------------------------------------------------------------------- - /** Parse a line in the skeleton section - */ - void ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime); - - // ------------------------------------------------------------------- - /** Parse a line in the nodes section - */ - void ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut); - - - // ------------------------------------------------------------------- - /** Parse a floating-point value - */ - bool ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out); - - // ------------------------------------------------------------------- - /** Parse an unsigned integer. There may be no sign! - */ - bool ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out); - - // ------------------------------------------------------------------- - /** Parse a signed integer. Signs (+,-) are handled. - */ - bool ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out); - - // ------------------------------------------------------------------- - /** Fix invalid time values in the file - */ - void FixTimeValues(); - - // ------------------------------------------------------------------- - /** Add all children of a bone as subnodes to a node - * \param pcNode Parent node - * \param iParent Parent bone index - */ - void AddBoneChildren(aiNode* pcNode, uint32_t iParent); - - // ------------------------------------------------------------------- - /** Build output meshes/materials/nodes/animations - */ - void CreateOutputMeshes(); - void CreateOutputNodes(); - void CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler); - void CreateOutputAnimation(int index, const std::string &name); - void GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector<std::tuple<std::string, std::string>>& outList); - void CreateOutputMaterials(); - - - // ------------------------------------------------------------------- - /** Print a log message together with the current line number - */ - void LogErrorNoThrow(const char* msg); - void LogWarning(const char* msg); - - - // ------------------------------------------------------------------- - inline bool SkipLine( const char* in, const char** out) - { - Assimp::SkipLine(in,out); - ++iLineNumber; - return true; - } - // ------------------------------------------------------------------- - inline bool SkipSpacesAndLineEnd( const char* in, const char** out) - { - ++iLineNumber; - return Assimp::SkipSpacesAndLineEnd(in,out); - } - -private: - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Buffer to hold the loaded file */ - std::vector<char> mBuffer; - - /** Output scene to be filled - */ - aiScene* pScene; - - /** Size of the input file in bytes - */ - unsigned int iFileSize; - - /** Array of textures found in the file - */ - std::vector<std::string> aszTextures; - - /** Array of triangles found in the file - */ - std::vector<SMD::Face> asTriangles; - - /** Array of bones found in the file - */ - std::vector<SMD::Bone> asBones; - - /** Smallest frame index found in the skeleton - */ - int iSmallestFrame; - - /** Length of the whole animation, in frames - */ - double dLengthOfAnim; - - /** Do we have texture coordinates? - */ - bool bHasUVs; - - /** Current line number - */ - unsigned int iLineNumber; - - bool bLoadAnimationList = true; - bool noSkeletonMesh = false; -}; - -} // end of namespace Assimp - -#endif // AI_SMDIMPORTER_H_INC |