Merge branch 'master' into trim-whitespace

pull/4882/head
Kim Kulling 2023-01-22 16:37:43 +01:00 committed by GitHub
commit 303c30668f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 84 deletions

View File

@ -1,6 +1,6 @@
# Open Asset Import Library (assimp) # Open Asset Import Library (assimp)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Copyright (c) 2006-2022, assimp team # Copyright (c) 2006-2023, assimp team
# #
# All rights reserved. # All rights reserved.
# #
@ -277,13 +277,15 @@ ELSEIF(MSVC)
ELSE() # msvc ELSE() # msvc
ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX) ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
ENDIF() ENDIF()
# disable "elements of array '' will be default initialized" warning on MSVC2013 # disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12) IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
ADD_COMPILE_OPTIONS(/wd4244) #supress warning for double to float conversion if Double precission is activated # supress warning for double to float conversion if Double precission is activated
ADD_COMPILE_OPTIONS(/wd4244)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)

View File

@ -762,6 +762,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
if (text == nullptr) { if (text == nullptr) {
throw DeadlyImportError("Out of data while reading <vertex_weights>"); throw DeadlyImportError("Out of data while reading <vertex_weights>");
} }
SkipSpacesAndLineEnd(&text);
it->first = strtoul10(text, &text); it->first = strtoul10(text, &text);
SkipSpacesAndLineEnd(&text); SkipSpacesAndLineEnd(&text);
if (*text == 0) { if (*text == 0) {

View File

@ -39,8 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER #if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)
#include "M3DWrapper.h" #include "M3DWrapper.h"
@ -149,4 +148,3 @@ void M3DWrapper::ClearSave() {
} // namespace Assimp } // namespace Assimp
#endif #endif
#endif

View File

@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_M3DWRAPPER_H_INC #ifndef AI_M3DWRAPPER_H_INC
#define AI_M3DWRAPPER_H_INC #define AI_M3DWRAPPER_H_INC
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER #if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -126,7 +125,6 @@ inline m3d_t *M3DWrapper::M3D() const {
} // namespace Assimp } // namespace Assimp
#endif
#endif // ASSIMP_BUILD_NO_M3D_IMPORTER #endif // ASSIMP_BUILD_NO_M3D_IMPORTER
#endif // AI_M3DWRAPPER_H_INC #endif // AI_M3DWRAPPER_H_INC

View File

@ -105,7 +105,11 @@ void JoinVerticesProcess::Execute( aiScene* pScene) {
namespace { namespace {
bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) { bool areVerticesEqual(
const Vertex &lhs,
const Vertex &rhs,
unsigned numUVChannels,
unsigned numColorChannels) {
// A little helper to find locally close vertices faster. // A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step. // Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f; const static float epsilon = 1e-5f;
@ -124,10 +128,6 @@ bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) {
return false; return false;
} }
if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) { if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
return false; return false;
} }
@ -136,19 +136,18 @@ bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) {
return false; return false;
} }
// Usually we won't have vertex colors or multiple UVs, so we can skip from here for (unsigned i = 0; i < numUVChannels; i++) {
// Actually this increases runtime performance slightly, at least if branch if ((lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
// prediction is on our side.
if (complex) {
for (int i = 0; i < 8; i++) {
if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
return false; return false;
} }
}
for (unsigned i = 0; i < numColorChannels; i++) {
if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) { if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
return false; return false;
} }
} }
}
return true; return true;
} }
@ -241,9 +240,16 @@ struct std::hash<Vertex> {
//template specialization for std::equal_to for Vertex //template specialization for std::equal_to for Vertex
template<> template<>
struct std::equal_to<Vertex> { struct std::equal_to<Vertex> {
equal_to(unsigned numUVChannels, unsigned numColorChannels) :
mNumUVChannels(numUVChannels),
mNumColorChannels(numColorChannels) {}
bool operator()(const Vertex &lhs, const Vertex &rhs) const { bool operator()(const Vertex &lhs, const Vertex &rhs) const {
return areVerticesEqual(lhs, rhs, false); return areVerticesEqual(lhs, rhs, mNumUVChannels, mNumColorChannels);
} }
private:
unsigned mNumUVChannels;
unsigned mNumColorChannels;
}; };
// now start the JoinVerticesProcess // now start the JoinVerticesProcess
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
@ -316,8 +322,13 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices); uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
} }
} }
// a map that maps a vertix to its new index // a map that maps a vertex to its new index
std::unordered_map<Vertex,int> vertex2Index; const auto numBuckets = pMesh->mNumVertices;
const auto hasher = std::hash<Vertex>();
const auto comparator = std::equal_to<Vertex>(
pMesh->GetNumUVChannels(),
pMesh->GetNumColorChannels());
std::unordered_map<Vertex, int> vertex2Index(numBuckets, hasher, comparator);
// we can not end up with more vertices than we started with // we can not end up with more vertices than we started with
vertex2Index.reserve(pMesh->mNumVertices); vertex2Index.reserve(pMesh->mNumVertices);
// Now check each vertex if it brings something new to the table // Now check each vertex if it brings something new to the table

View File

@ -2,8 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2023, assimp team
All rights reserved. All rights reserved.
@ -36,13 +35,7 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- */
----------------------------------------------------------------------
*/
/** Implementation of the LimitBoneWeightsProcess post processing step */
#include "LimitBoneWeightsProcess.h" #include "LimitBoneWeightsProcess.h"
#include <assimp/SmallVector.h> #include <assimp/SmallVector.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -51,14 +44,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <stdio.h> #include <stdio.h>
using namespace Assimp; namespace Assimp {
// Make sure this value is set.
#ifndef AI_LMW_MAX_WEIGHTS
# define AI_LMW_MAX_WEIGHTS 16
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess() LimitBoneWeightsProcess::LimitBoneWeightsProcess() : mMaxWeights(AI_LMW_MAX_WEIGHTS) {}
{
mMaxWeights = AI_LMW_MAX_WEIGHTS;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
@ -66,15 +61,15 @@ LimitBoneWeightsProcess::~LimitBoneWeightsProcess() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const {
{
return (pFlags & aiProcess_LimitBoneWeights) != 0; return (pFlags & aiProcess_LimitBoneWeights) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::Execute( aiScene* pScene) void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
{ ai_assert(pScene != nullptr);
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin"); ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) { for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
@ -86,16 +81,30 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
{
// get the current value of the property
this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS); this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
} }
// ------------------------------------------------------------------------------------------------
static unsigned int removeEmptyBones(aiMesh *pMesh) {
ai_assert(pMesh != nullptr);
unsigned int writeBone = 0;
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) {
aiBone* bone = pMesh->mBones[readBone];
if (bone->mNumWeights > 0) {
pMesh->mBones[writeBone++] = bone;
} else {
delete bone;
}
}
return writeBone;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh // Unites identical vertices in the given mesh
void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) {
{
if (!pMesh->HasBones()) if (!pMesh->HasBones())
return; return;
@ -105,11 +114,9 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
WeightsPerVertex vertexWeights(pMesh->mNumVertices); WeightsPerVertex vertexWeights(pMesh->mNumVertices);
size_t maxVertexWeights = 0; size_t maxVertexWeights = 0;
for (unsigned int b = 0; b < pMesh->mNumBones; ++b) for (unsigned int b = 0; b < pMesh->mNumBones; ++b) {
{
const aiBone* bone = pMesh->mBones[b]; const aiBone* bone = pMesh->mBones[b];
for (unsigned int w = 0; w < bone->mNumWeights; ++w) for (unsigned int w = 0; w < bone->mNumWeights; ++w) {
{
const aiVertexWeight& vw = bone->mWeights[w]; const aiVertexWeight& vw = bone->mWeights[w];
if (vertexWeights.size() <= vw.mVertexId) if (vertexWeights.size() <= vw.mVertexId)
@ -126,8 +133,7 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
unsigned int removed = 0, old_bones = pMesh->mNumBones; unsigned int removed = 0, old_bones = pMesh->mNumBones;
// now cut the weight count if it exceeds the maximum // now cut the weight count if it exceeds the maximum
for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) {
{
if (vit->size() <= mMaxWeights) if (vit->size() <= mMaxWeights)
continue; continue;
@ -154,40 +160,27 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
} }
// clear weight count for all bone // clear weight count for all bone
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
{
pMesh->mBones[a]->mNumWeights = 0; pMesh->mBones[a]->mNumWeights = 0;
} }
// rebuild the vertex weight array for all bones // rebuild the vertex weight array for all bones
for (unsigned int a = 0; a < vertexWeights.size(); ++a) for (unsigned int a = 0; a < vertexWeights.size(); ++a) {
{
const VertexWeightArray& vw = vertexWeights[a]; const VertexWeightArray& vw = vertexWeights[a];
for (const Weight* it = vw.begin(); it != vw.end(); ++it) for (const Weight* it = vw.begin(); it != vw.end(); ++it) {
{
aiBone* bone = pMesh->mBones[it->mBone]; aiBone* bone = pMesh->mBones[it->mBone];
bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight); bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
} }
} }
// remove empty bones // remove empty bones
unsigned int writeBone = 0; #ifdef AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
pMesh->mNumBones = removeEmptyBones(pMesh);
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) #endif // AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
{
aiBone* bone = pMesh->mBones[readBone];
if (bone->mNumWeights > 0)
{
pMesh->mBones[writeBone++] = bone;
}
else
{
delete bone;
}
}
pMesh->mNumBones = writeBone;
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones); ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
} }
} }
} // namespace Assimp