From 058f98a63658dc1a2579826ba167fd61bed1e21f Mon Sep 17 00:00:00 2001 From: sanine Date: Fri, 4 Mar 2022 10:47:15 -0600 Subject: add assimp submodule --- .../code/PostProcessing/ProcessHelper.cpp | 383 +++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 src/mesh/assimp-master/code/PostProcessing/ProcessHelper.cpp (limited to 'src/mesh/assimp-master/code/PostProcessing/ProcessHelper.cpp') diff --git a/src/mesh/assimp-master/code/PostProcessing/ProcessHelper.cpp b/src/mesh/assimp-master/code/PostProcessing/ProcessHelper.cpp new file mode 100644 index 0000000..6f0a798 --- /dev/null +++ b/src/mesh/assimp-master/code/PostProcessing/ProcessHelper.cpp @@ -0,0 +1,383 @@ +/* +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 ProcessHelper.cpp +/** Implement shared utility functions for postprocessing steps */ + +#include "ProcessHelper.h" + +#include + +namespace Assimp { + +// ------------------------------------------------------------------------------- +void ConvertListToStrings(const std::string &in, std::list &out) { + const char *s = in.c_str(); + while (*s) { + SkipSpacesAndLineEnd(&s); + if (*s == '\'') { + const char *base = ++s; + while (*s != '\'') { + ++s; + if (*s == '\0') { + ASSIMP_LOG_ERROR("ConvertListToString: String list is ill-formatted"); + return; + } + } + out.push_back(std::string(base, (size_t)(s - base))); + ++s; + } else { + out.push_back(GetNextToken(s)); + } + } +} + +// ------------------------------------------------------------------------------- +void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, + const aiMatrix4x4 &m) { + min = aiVector3D(ai_real(10e10), ai_real(10e10), ai_real(10e10)); + max = aiVector3D(ai_real(-10e10), ai_real(-10e10), ai_real(-10e10)); + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + const aiVector3D v = m * mesh->mVertices[i]; + min = std::min(v, min); + max = std::max(v, max); + } +} + +// ------------------------------------------------------------------------------- +void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max) { + ArrayBounds(mesh->mVertices, mesh->mNumVertices, min, max); + out = min + (max - min) * (ai_real)0.5; +} + +// ------------------------------------------------------------------------------- +void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max) { + if (nullptr == scene) { + return; + } + + if (0 == scene->mNumMeshes) { + return; + } + FindMeshCenter(scene->mMeshes[0], out, min, max); + for (unsigned int i = 1; i < scene->mNumMeshes; ++i) { + aiVector3D tout, tmin, tmax; + FindMeshCenter(scene->mMeshes[i], tout, tmin, tmax); + if (min[0] > tmin[0]) min[0] = tmin[0]; + if (min[1] > tmin[1]) min[1] = tmin[1]; + if (min[2] > tmin[2]) min[2] = tmin[2]; + if (max[0] < tmax[0]) max[0] = tmax[0]; + if (max[1] < tmax[1]) max[1] = tmax[1]; + if (max[2] < tmax[2]) max[2] = tmax[2]; + } + out = min + (max - min) * (ai_real)0.5; +} + +// ------------------------------------------------------------------------------- +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, + aiVector3D &max, const aiMatrix4x4 &m) { + FindAABBTransformed(mesh, min, max, m); + out = min + (max - min) * (ai_real)0.5; +} + +// ------------------------------------------------------------------------------- +void FindMeshCenter(aiMesh *mesh, aiVector3D &out) { + aiVector3D min, max; + FindMeshCenter(mesh, out, min, max); +} + +// ------------------------------------------------------------------------------- +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, + const aiMatrix4x4 &m) { + aiVector3D min, max; + FindMeshCenterTransformed(mesh, out, min, max, m); +} + +// ------------------------------------------------------------------------------- +ai_real ComputePositionEpsilon(const aiMesh *pMesh) { + const ai_real epsilon = ai_real(1e-4); + + // calculate the position bounds so we have a reliable epsilon to check position differences against + aiVector3D minVec, maxVec; + ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, minVec, maxVec); + return (maxVec - minVec).Length() * epsilon; +} + +// ------------------------------------------------------------------------------- +ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num) { + ai_assert(nullptr != pMeshes); + + const ai_real epsilon = ai_real(1e-4); + + // calculate the position bounds so we have a reliable epsilon to check position differences against + aiVector3D minVec, maxVec, mi, ma; + MinMaxChooser()(minVec, maxVec); + + for (size_t a = 0; a < num; ++a) { + const aiMesh *pMesh = pMeshes[a]; + ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, mi, ma); + + minVec = std::min(minVec, mi); + maxVec = std::max(maxVec, ma); + } + return (maxVec - minVec).Length() * epsilon; +} + +// ------------------------------------------------------------------------------- +unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) { + ai_assert(nullptr != pcMesh); + + // FIX: the hash may never be 0. Otherwise a comparison against + // nullptr could be successful + unsigned int iRet = 1; + + // normals + if (pcMesh->HasNormals()) iRet |= 0x2; + // tangents and bitangents + if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4; + +#ifdef BOOST_STATIC_ASSERT + BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); + BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); +#endif + + // texture coordinates + unsigned int p = 0; + while (pcMesh->HasTextureCoords(p)) { + iRet |= (0x100 << p); + if (3 == pcMesh->mNumUVComponents[p]) + iRet |= (0x10000 << p); + + ++p; + } + // vertex colors + p = 0; + while (pcMesh->HasVertexColors(p)) + iRet |= (0x1000000 << p++); + return iRet; +} + +// ------------------------------------------------------------------------------- +VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh) { + if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) { + return nullptr; + } + + VertexWeightTable *avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; + for (unsigned int i = 0; i < pMesh->mNumBones; ++i) { + + aiBone *bone = pMesh->mBones[i]; + for (unsigned int a = 0; a < bone->mNumWeights; ++a) { + const aiVertexWeight &weight = bone->mWeights[a]; + avPerVertexWeights[weight.mVertexId].push_back(std::pair(i, weight.mWeight)); + } + } + return avPerVertexWeights; +} + +// ------------------------------------------------------------------------------- +const char *MappingTypeToString(aiTextureMapping in) { + switch (in) { + case aiTextureMapping_UV: + return "UV"; + case aiTextureMapping_BOX: + return "Box"; + case aiTextureMapping_SPHERE: + return "Sphere"; + case aiTextureMapping_CYLINDER: + return "Cylinder"; + case aiTextureMapping_PLANE: + return "Plane"; + case aiTextureMapping_OTHER: + return "Other"; + default: + break; + } + + ai_assert(false); + return "BUG"; +} + +// ------------------------------------------------------------------------------- +aiMesh *MakeSubmesh(const aiMesh *pMesh, const std::vector &subMeshFaces, unsigned int subFlags) { + aiMesh *oMesh = new aiMesh(); + std::vector vMap(pMesh->mNumVertices, UINT_MAX); + + size_t numSubVerts = 0; + size_t numSubFaces = subMeshFaces.size(); + + for (unsigned int i = 0; i < numSubFaces; i++) { + const aiFace &f = pMesh->mFaces[subMeshFaces[i]]; + + for (unsigned int j = 0; j < f.mNumIndices; j++) { + if (vMap[f.mIndices[j]] == UINT_MAX) { + vMap[f.mIndices[j]] = static_cast(numSubVerts++); + } + } + } + + oMesh->mName = pMesh->mName; + + oMesh->mMaterialIndex = pMesh->mMaterialIndex; + oMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; + + // create all the arrays for this mesh if the old mesh contained them + + oMesh->mNumFaces = static_cast(subMeshFaces.size()); + oMesh->mNumVertices = static_cast(numSubVerts); + oMesh->mVertices = new aiVector3D[numSubVerts]; + if (pMesh->HasNormals()) { + oMesh->mNormals = new aiVector3D[numSubVerts]; + } + + if (pMesh->HasTangentsAndBitangents()) { + oMesh->mTangents = new aiVector3D[numSubVerts]; + oMesh->mBitangents = new aiVector3D[numSubVerts]; + } + + for (size_t a = 0; pMesh->HasTextureCoords(static_cast(a)); ++a) { + oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts]; + oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; + } + + for (size_t a = 0; pMesh->HasVertexColors(static_cast(a)); ++a) { + oMesh->mColors[a] = new aiColor4D[numSubVerts]; + } + + // and copy over the data, generating faces with linear indices along the way + oMesh->mFaces = new aiFace[numSubFaces]; + + for (unsigned int a = 0; a < numSubFaces; ++a) { + + const aiFace &srcFace = pMesh->mFaces[subMeshFaces[a]]; + aiFace &dstFace = oMesh->mFaces[a]; + dstFace.mNumIndices = srcFace.mNumIndices; + dstFace.mIndices = new unsigned int[dstFace.mNumIndices]; + + // accumulate linearly all the vertices of the source face + for (size_t b = 0; b < dstFace.mNumIndices; ++b) { + dstFace.mIndices[b] = vMap[srcFace.mIndices[b]]; + } + } + + for (unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex) { + unsigned int nvi = vMap[srcIndex]; + if (nvi == UINT_MAX) { + continue; + } + + oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex]; + if (pMesh->HasNormals()) { + oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; + } + + if (pMesh->HasTangentsAndBitangents()) { + oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; + oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex]; + } + for (size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c) { + oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; + } + for (size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c) { + oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; + } + } + + if (~subFlags & AI_SUBMESH_FLAGS_SANS_BONES) { + std::vector subBones(pMesh->mNumBones, 0); + + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + const aiBone *bone = pMesh->mBones[a]; + + for (unsigned int b = 0; b < bone->mNumWeights; b++) { + unsigned int v = vMap[bone->mWeights[b].mVertexId]; + + if (v != UINT_MAX) { + subBones[a]++; + } + } + } + + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + if (subBones[a] > 0) { + oMesh->mNumBones++; + } + } + + if (oMesh->mNumBones) { + oMesh->mBones = new aiBone *[oMesh->mNumBones](); + unsigned int nbParanoia = oMesh->mNumBones; + + oMesh->mNumBones = 0; //rewind + + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + if (subBones[a] == 0) { + continue; + } + aiBone *newBone = new aiBone; + oMesh->mBones[oMesh->mNumBones++] = newBone; + + const aiBone *bone = pMesh->mBones[a]; + + newBone->mName = bone->mName; + newBone->mOffsetMatrix = bone->mOffsetMatrix; + newBone->mWeights = new aiVertexWeight[subBones[a]]; + + for (unsigned int b = 0; b < bone->mNumWeights; b++) { + const unsigned int v = vMap[bone->mWeights[b].mVertexId]; + + if (v != UINT_MAX) { + aiVertexWeight w(v, bone->mWeights[b].mWeight); + newBone->mWeights[newBone->mNumWeights++] = w; + } + } + } + + ai_assert(nbParanoia == oMesh->mNumBones); + (void)nbParanoia; // remove compiler warning on release build + } + } + + return oMesh; +} + +} // namespace Assimp -- cgit v1.2.1