replace NULL and avoid ai_assert with more than 2 tests.

This commit is contained in:
Kim Kulling
2020-06-23 21:05:42 +02:00
659 changed files with 30283 additions and 48642 deletions

View File

@@ -82,7 +82,7 @@ void ArmaturePopulate::Execute(aiScene *out) {
for (std::pair<aiBone *, aiNode *> kvp : bone_stack) {
aiBone *bone = kvp.first;
aiNode *bone_node = kvp.second;
ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str());
ASSIMP_LOG_VERBOSE_DEBUG_F("active node lookup: ", bone->mName.C_Str());
// lcl transform grab - done in generate_nodes :)
// bone->mOffsetMatrix = bone_node->mTransformation;
@@ -178,7 +178,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *,
if (node == nullptr) {
node_stack.clear();
BuildNodeList(root_node, node_stack);
ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
node = GetNodeFromStack(bone->mName, node_stack);
@@ -188,7 +188,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *,
}
}
ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str());
ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str());
bone_stack.insert(std::pair<aiBone *, aiNode *>(bone, node));
}
@@ -202,7 +202,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list) {
while (bone_node) {
if (!IsBoneNode(bone_node->mName, bone_list)) {
ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
return bone_node;
}

View File

@@ -109,4 +109,4 @@ public:
} // Namespace Assimp
#endif // SCALE_PROCESS_H_
#endif // SCALE_PROCESS_H_

View File

@@ -55,54 +55,49 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
CalcTangentsProcess::CalcTangentsProcess()
: configMaxAngle( AI_DEG_TO_RAD(45.f) )
, configSourceUV( 0 ) {
CalcTangentsProcess::CalcTangentsProcess() :
configMaxAngle(AI_DEG_TO_RAD(45.f)), configSourceUV(0) {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
CalcTangentsProcess::~CalcTangentsProcess()
{
CalcTangentsProcess::~CalcTangentsProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
{
bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_CalcTangentSpace) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void CalcTangentsProcess::SetupProperties(const Importer* pImp)
{
ai_assert( NULL != pImp );
void CalcTangentsProcess::SetupProperties(const Importer *pImp) {
ai_assert(nullptr != pImp);
// get the current value of the property
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, 45.f);
configMaxAngle = std::max(std::min(configMaxAngle, 45.0f), 0.0f);
configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX, 0);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void CalcTangentsProcess::Execute( aiScene* pScene)
{
ai_assert( NULL != pScene );
void CalcTangentsProcess::Execute(aiScene *pScene) {
ai_assert(nullptr != pScene);
ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
bool bHas = false;
for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if (ProcessMesh(pScene->mMeshes[a], a)) bHas = true;
}
if ( bHas ) {
if (bHas) {
ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
} else {
ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
@@ -111,8 +106,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
// Calculates tangents and bi-tangents for the given mesh
bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
{
bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
// we assume that the mesh is still in the verbose vertex format where each face has its own set
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
// assert() it here.
@@ -124,54 +118,48 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors
// are undefined.
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
{
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
return false;
}
// what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
if( pMesh->mNormals == NULL)
{
if (pMesh->mNormals == nullptr) {
ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
return false;
}
if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
{
ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
if (configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV]) {
ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"), configSourceUV));
return false;
}
const float angleEpsilon = 0.9999f;
std::vector<bool> vertexDone( pMesh->mNumVertices, false);
std::vector<bool> vertexDone(pMesh->mNumVertices, false);
const float qnan = get_qnan();
// create space for the tangents and bitangents
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
const aiVector3D* meshPos = pMesh->mVertices;
const aiVector3D* meshNorm = pMesh->mNormals;
const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
aiVector3D* meshTang = pMesh->mTangents;
aiVector3D* meshBitang = pMesh->mBitangents;
const aiVector3D *meshPos = pMesh->mVertices;
const aiVector3D *meshNorm = pMesh->mNormals;
const aiVector3D *meshTex = pMesh->mTextureCoords[configSourceUV];
aiVector3D *meshTang = pMesh->mTangents;
aiVector3D *meshBitang = pMesh->mBitangents;
// calculate the tangent and bitangent for every face
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
const aiFace& face = pMesh->mFaces[a];
if (face.mNumIndices < 3)
{
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace &face = pMesh->mFaces[a];
if (face.mNumIndices < 3) {
// There are less than three indices, thus the tangent vector
// is not defined. We are finished with these vertices now,
// their tangent vectors are set to qnan.
for (unsigned int i = 0; i < face.mNumIndices;++i)
{
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
unsigned int idx = face.mIndices[i];
vertexDone [idx] = true;
meshTang [idx] = aiVector3D(qnan);
meshBitang [idx] = aiVector3D(qnan);
vertexDone[idx] = true;
meshTang[idx] = aiVector3D(qnan);
meshBitang[idx] = aiVector3D(qnan);
}
continue;
@@ -190,9 +178,11 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
// when t1, t2, t3 in same position in UV space, just use default UV direction.
if ( sx * ty == sy * tx ) {
sx = 0.0; sy = 1.0;
tx = 1.0; ty = 0.0;
if (sx * ty == sy * tx) {
sx = 0.0;
sy = 1.0;
tx = 1.0;
ty = 0.0;
}
// tangent points in the direction where to positive X axis of the texture coord's would point in model space
@@ -206,13 +196,14 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
// store for every vertex of that face
for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
for (unsigned int b = 0; b < face.mNumIndices; ++b) {
unsigned int p = face.mIndices[b];
// project tangent and bitangent into the plane formed by the vertex' normal
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
localTangent.NormalizeSafe(); localBitangent.NormalizeSafe();
localTangent.NormalizeSafe();
localBitangent.NormalizeSafe();
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
@@ -228,31 +219,28 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
}
// and write it into the mesh.
meshTang[ p ] = localTangent;
meshBitang[ p ] = localBitangent;
meshTang[p] = localTangent;
meshBitang[p] = localBitangent;
}
}
// create a helper to quickly find locally close vertices among the vertex array
// FIX: check whether we can reuse the SpatialSort of a previous step
SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder;
SpatialSort *vertexFinder = nullptr;
SpatialSort _vertexFinder;
float posEpsilon = 10e-6f;
if (shared)
{
std::vector<std::pair<SpatialSort,float> >* avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
if (avf)
{
std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
if (shared) {
std::vector<std::pair<SpatialSort, float>> *avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
if (avf) {
std::pair<SpatialSort, float> &blubb = avf->operator[](meshIndex);
vertexFinder = &blubb.first;
posEpsilon = blubb.second;;
posEpsilon = blubb.second;
;
}
}
if (!vertexFinder)
{
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
if (!vertexFinder) {
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
vertexFinder = &_vertexFinder;
posEpsilon = ComputePositionEpsilon(pMesh);
}
@@ -263,56 +251,52 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// in the second pass we now smooth out all tangents and bitangents at the same local position
// if they are not too far off.
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
{
if( vertexDone[a])
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
if (vertexDone[a])
continue;
const aiVector3D& origPos = pMesh->mVertices[a];
const aiVector3D& origNorm = pMesh->mNormals[a];
const aiVector3D& origTang = pMesh->mTangents[a];
const aiVector3D& origBitang = pMesh->mBitangents[a];
closeVertices.resize( 0 );
const aiVector3D &origPos = pMesh->mVertices[a];
const aiVector3D &origNorm = pMesh->mNormals[a];
const aiVector3D &origTang = pMesh->mTangents[a];
const aiVector3D &origBitang = pMesh->mBitangents[a];
closeVertices.resize(0);
// find all vertices close to that position
vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
vertexFinder->FindPositions(origPos, posEpsilon, verticesFound);
closeVertices.reserve (verticesFound.size()+5);
closeVertices.push_back( a);
closeVertices.reserve(verticesFound.size() + 5);
closeVertices.push_back(a);
// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
for( unsigned int b = 0; b < verticesFound.size(); b++)
{
for (unsigned int b = 0; b < verticesFound.size(); b++) {
unsigned int idx = verticesFound[b];
if( vertexDone[idx])
if (vertexDone[idx])
continue;
if( meshNorm[idx] * origNorm < angleEpsilon)
if (meshNorm[idx] * origNorm < angleEpsilon)
continue;
if( meshTang[idx] * origTang < fLimit)
if (meshTang[idx] * origTang < fLimit)
continue;
if( meshBitang[idx] * origBitang < fLimit)
if (meshBitang[idx] * origBitang < fLimit)
continue;
// it's similar enough -> add it to the smoothing group
closeVertices.push_back( idx);
closeVertices.push_back(idx);
vertexDone[idx] = true;
}
// smooth the tangents and bitangents of all vertices that were found to be close enough
aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
for( unsigned int b = 0; b < closeVertices.size(); ++b)
{
smoothTangent += meshTang[ closeVertices[b] ];
smoothBitangent += meshBitang[ closeVertices[b] ];
aiVector3D smoothTangent(0, 0, 0), smoothBitangent(0, 0, 0);
for (unsigned int b = 0; b < closeVertices.size(); ++b) {
smoothTangent += meshTang[closeVertices[b]];
smoothBitangent += meshBitang[closeVertices[b]];
}
smoothTangent.Normalize();
smoothBitangent.Normalize();
// and write it back into all affected tangents
for( unsigned int b = 0; b < closeVertices.size(); ++b)
{
meshTang[ closeVertices[b] ] = smoothTangent;
meshBitang[ closeVertices[b] ] = smoothBitangent;
for (unsigned int b = 0; b < closeVertices.size(); ++b) {
meshTang[closeVertices[b]] = smoothTangent;
meshBitang[closeVertices[b]] = smoothBitangent;
}
}
return true;

View File

@@ -49,10 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* better location.
*/
#include "ConvertToLHProcess.h"
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
@@ -62,8 +61,10 @@ using namespace Assimp;
namespace {
template <typename aiMeshType>
void flipUVs(aiMeshType* pMesh) {
if (pMesh == nullptr) { return; }
void flipUVs(aiMeshType *pMesh) {
if (pMesh == nullptr) {
return;
}
// mirror texture y coordinate
for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) {
if (!pMesh->HasTextureCoords(tcIdx)) {
@@ -80,8 +81,8 @@ void flipUVs(aiMeshType* pMesh) {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MakeLeftHandedProcess::MakeLeftHandedProcess()
: BaseProcess() {
MakeLeftHandedProcess::MakeLeftHandedProcess() :
BaseProcess() {
// empty
}
@@ -93,40 +94,36 @@ MakeLeftHandedProcess::~MakeLeftHandedProcess() {
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
{
bool MakeLeftHandedProcess::IsActive(unsigned int pFlags) const {
return 0 != (pFlags & aiProcess_MakeLeftHanded);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeLeftHandedProcess::Execute( aiScene* pScene)
{
void MakeLeftHandedProcess::Execute(aiScene *pScene) {
// Check for an existent root node to proceed
ai_assert(pScene->mRootNode != NULL);
ai_assert(pScene->mRootNode != nullptr);
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
// recursively convert all the nodes
ProcessNode( pScene->mRootNode, aiMatrix4x4());
ProcessNode(pScene->mRootNode, aiMatrix4x4());
// process the meshes accordingly
for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
ProcessMesh( pScene->mMeshes[ a ] );
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
ProcessMesh(pScene->mMeshes[a]);
}
// process the materials accordingly
for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
ProcessMaterial( pScene->mMaterials[ a ] );
for (unsigned int a = 0; a < pScene->mNumMaterials; ++a) {
ProcessMaterial(pScene->mMaterials[a]);
}
// transform all animation channels as well
for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
{
aiAnimation* anim = pScene->mAnimations[a];
for( unsigned int b = 0; b < anim->mNumChannels; b++)
{
aiNodeAnim* nodeAnim = anim->mChannels[b];
ProcessAnimation( nodeAnim);
for (unsigned int a = 0; a < pScene->mNumAnimations; a++) {
aiAnimation *anim = pScene->mAnimations[a];
for (unsigned int b = 0; b < anim->mNumChannels; b++) {
aiNodeAnim *nodeAnim = anim->mChannels[b];
ProcessAnimation(nodeAnim);
}
}
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
@@ -134,8 +131,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
// Recursively converts a node, all of its children and all of its meshes
void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
{
void MakeLeftHandedProcess::ProcessNode(aiNode *pNode, const aiMatrix4x4 &pParentGlobalRotation) {
// mirror all base vectors at the local Z axis
pNode->mTransformation.c1 = -pNode->mTransformation.c1;
pNode->mTransformation.c2 = -pNode->mTransformation.c2;
@@ -150,43 +146,38 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
// continue for all children
for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
for (size_t a = 0; a < pNode->mNumChildren; ++a) {
ProcessNode(pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
}
}
// ------------------------------------------------------------------------------------------------
// Converts a single mesh to left handed coordinates.
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
if ( nullptr == pMesh ) {
ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
void MakeLeftHandedProcess::ProcessMesh(aiMesh *pMesh) {
if (nullptr == pMesh) {
ASSIMP_LOG_ERROR("Nullptr to mesh found.");
return;
}
// mirror positions, normals and stuff along the Z axis
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
{
for (size_t a = 0; a < pMesh->mNumVertices; ++a) {
pMesh->mVertices[a].z *= -1.0f;
if (pMesh->HasNormals()) {
pMesh->mNormals[a].z *= -1.0f;
}
if( pMesh->HasTangentsAndBitangents())
{
if (pMesh->HasTangentsAndBitangents()) {
pMesh->mTangents[a].z *= -1.0f;
pMesh->mBitangents[a].z *= -1.0f;
}
}
// mirror anim meshes positions, normals and stuff along the Z axis
for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m)
{
for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a)
{
for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m) {
for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a) {
pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f;
if (pMesh->mAnimMeshes[m]->HasNormals()) {
pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f;
}
if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents())
{
if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents()) {
pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f;
pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f;
}
@@ -194,9 +185,8 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
}
// mirror offset matrices of all bones
for( size_t a = 0; a < pMesh->mNumBones; ++a)
{
aiBone* bone = pMesh->mBones[a];
for (size_t a = 0; a < pMesh->mNumBones; ++a) {
aiBone *bone = pMesh->mBones[a];
bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
@@ -206,29 +196,28 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
}
// mirror bitangents as well as they're derived from the texture coords
if( pMesh->HasTangentsAndBitangents())
{
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
if (pMesh->HasTangentsAndBitangents()) {
for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mBitangents[a] *= -1.0f;
}
}
// ------------------------------------------------------------------------------------------------
// Converts a single material to left handed coordinates.
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
if ( nullptr == _mat ) {
ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
void MakeLeftHandedProcess::ProcessMaterial(aiMaterial *_mat) {
if (nullptr == _mat) {
ASSIMP_LOG_ERROR("Nullptr to aiMaterial found.");
return;
}
aiMaterial* mat = (aiMaterial*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a];
aiMaterial *mat = (aiMaterial *)_mat;
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
aiMaterialProperty *prop = mat->mProperties[a];
// Mapping axis for UV mappings?
if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
aiVector3D* pff = (aiVector3D*)prop->mData;
if (!::strcmp(prop->mKey.data, "$tex.mapaxis")) {
ai_assert(prop->mDataLength >= sizeof(aiVector3D)); // something is wrong with the validation if we end up here
aiVector3D *pff = (aiVector3D *)prop->mData;
pff->z *= -1.f;
}
}
@@ -236,15 +225,13 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
// ------------------------------------------------------------------------------------------------
// Converts the given animation to LH coordinates.
void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
{
void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) {
// position keys
for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
for (unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
pAnim->mPositionKeys[a].mValue.z *= -1.0f;
// rotation keys
for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
{
for (unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) {
/* That's the safe version, but the float errors add up. So we try the short version instead
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
@@ -258,55 +245,50 @@ void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
}
#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
// # FlipUVsProcess
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FlipUVsProcess::FlipUVsProcess()
{}
FlipUVsProcess::FlipUVsProcess() {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FlipUVsProcess::~FlipUVsProcess()
{}
FlipUVsProcess::~FlipUVsProcess() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FlipUVsProcess::IsActive( unsigned int pFlags) const
{
bool FlipUVsProcess::IsActive(unsigned int pFlags) const {
return 0 != (pFlags & aiProcess_FlipUVs);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipUVsProcess::Execute( aiScene* pScene)
{
void FlipUVsProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
ProcessMesh(pScene->mMeshes[i]);
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i)
ProcessMaterial(pScene->mMaterials[i]);
ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Converts a single material
void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
{
aiMaterial* mat = (aiMaterial*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a];
if( !prop ) {
ASSIMP_LOG_DEBUG( "Property is null" );
void FlipUVsProcess::ProcessMaterial(aiMaterial *_mat) {
aiMaterial *mat = (aiMaterial *)_mat;
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
aiMaterialProperty *prop = mat->mProperties[a];
if (!prop) {
ASSIMP_LOG_VERBOSE_DEBUG("Property is null");
continue;
}
// UV transformation key?
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
aiUVTransform* uv = (aiUVTransform*)prop->mData;
if (!::strcmp(prop->mKey.data, "$tex.uvtrafo")) {
ai_assert(prop->mDataLength >= sizeof(aiUVTransform)); // something is wrong with the validation if we end up here
aiUVTransform *uv = (aiUVTransform *)prop->mData;
// just flip it, that's everything
uv->mTranslation.y *= -1.f;
@@ -317,8 +299,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
// ------------------------------------------------------------------------------------------------
// Converts a single mesh
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{
void FlipUVsProcess::ProcessMesh(aiMesh *pMesh) {
flipUVs(pMesh);
for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
flipUVs(pMesh->mAnimMeshes[idx]);
@@ -326,44 +307,38 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
}
#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
// # FlipWindingOrderProcess
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FlipWindingOrderProcess::FlipWindingOrderProcess()
{}
FlipWindingOrderProcess::FlipWindingOrderProcess() {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FlipWindingOrderProcess::~FlipWindingOrderProcess()
{}
FlipWindingOrderProcess::~FlipWindingOrderProcess() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
{
bool FlipWindingOrderProcess::IsActive(unsigned int pFlags) const {
return 0 != (pFlags & aiProcess_FlipWindingOrder);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipWindingOrderProcess::Execute( aiScene* pScene)
{
void FlipWindingOrderProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
ProcessMesh(pScene->mMeshes[i]);
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Converts a single mesh
void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
{
void FlipWindingOrderProcess::ProcessMesh(aiMesh *pMesh) {
// invert the order of all faces in this mesh
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
aiFace& face = pMesh->mFaces[a];
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
aiFace &face = pMesh->mFaces[a];
for (unsigned int b = 0; b < face.mNumIndices / 2; b++) {
std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
}
@@ -371,39 +346,34 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
// invert the order of all components in this mesh anim meshes
for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) {
aiAnimMesh* animMesh = pMesh->mAnimMeshes[m];
aiAnimMesh *animMesh = pMesh->mAnimMeshes[m];
unsigned int numVertices = animMesh->mNumVertices;
if (animMesh->HasPositions()) {
for (unsigned int a = 0; a < numVertices; a++)
{
for (unsigned int a = 0; a < numVertices; a++) {
std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]);
}
}
if (animMesh->HasNormals()) {
for (unsigned int a = 0; a < numVertices; a++)
{
for (unsigned int a = 0; a < numVertices; a++) {
std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]);
}
}
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
if (animMesh->HasTextureCoords(i)) {
for (unsigned int a = 0; a < numVertices; a++)
{
for (unsigned int a = 0; a < numVertices; a++) {
std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]);
}
}
}
if (animMesh->HasTangentsAndBitangents()) {
for (unsigned int a = 0; a < numVertices; a++)
{
for (unsigned int a = 0; a < numVertices; a++) {
std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]);
std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]);
}
}
for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) {
if (animMesh->HasVertexColors(v)) {
for (unsigned int a = 0; a < numVertices; a++)
{
for (unsigned int a = 0; a < numVertices; a++) {
std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]);
}
}

View File

@@ -414,7 +414,8 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
}
if( pNode->mNumMeshes > 0 ) {
delete [] pNode->mMeshes; pNode->mMeshes = NULL;
delete[] pNode->mMeshes;
pNode->mMeshes = nullptr;
}
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());

View File

@@ -98,12 +98,14 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) {
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* pMesh) {
if (NULL == pMesh->mNormals) {
bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) {
ai_assert(nullptr != mesh);
if (nullptr == mesh->mNormals) {
return false;
}
delete[] pMesh->mNormals;
pMesh->mNormals = nullptr;
delete[] mesh->mNormals;
mesh->mNormals = nullptr;
return true;
}

View File

@@ -289,7 +289,7 @@ evil_jump_outside:
if (!mesh->mNumFaces) {
//The whole mesh consists of degenerated faces
//signal upward, that this mesh should be deleted.
ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
return true;
}
}

View File

@@ -243,7 +243,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
// Delete the instanced mesh, we don't need it anymore
delete inst;
pScene->mMeshes[i] = NULL;
pScene->mMeshes[i] = nullptr;
break;
}
}
@@ -256,7 +256,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
ai_assert(0 != numMeshesOut);
if (numMeshesOut != pScene->mNumMeshes) {
// Collapse the meshes array by removing all NULL entries
// Collapse the meshes array by removing all nullptr entries
for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
if (pScene->mMeshes[i])
pScene->mMeshes[real++] = pScene->mMeshes[i];

View File

@@ -45,11 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
// internal headers
# include "FindInvalidDataProcess.h"
# include "ProcessHelper.h"
#include "FindInvalidDataProcess.h"
#include "ProcessHelper.h"
# include <assimp/Exceptional.h>
# include <assimp/qnan.h>
#include <assimp/Exceptional.h>
#include <assimp/qnan.h>
using namespace Assimp;
@@ -97,7 +97,7 @@ void UpdateMeshReferences(aiNode *node, const std::vector<unsigned int> &meshMap
node->mNumMeshes = out;
if (0 == out) {
delete[] node->mMeshes;
node->mMeshes = NULL;
node->mMeshes = nullptr;
}
}
// recursively update all children
@@ -124,7 +124,7 @@ void FindInvalidDataProcess::Execute(aiScene *pScene) {
if (2 == result) {
// remove this mesh
delete pScene->mMeshes[a];
AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
pScene->mMeshes[a] = nullptr;
meshMapping[a] = UINT_MAX;
continue;
@@ -201,7 +201,7 @@ inline bool ProcessArray(T *&in, unsigned int num, const char *name,
if (err) {
ASSIMP_LOG_ERROR_F("FindInvalidDataProcess fails on mesh ", name, ": ", err);
delete[] in;
in = NULL;
in = nullptr;
return true;
}
return false;
@@ -345,7 +345,7 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) {
// delete all subsequent texture coordinate sets.
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
delete[] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = NULL;
pMesh->mTextureCoords[a] = nullptr;
pMesh->mNumUVComponents[a] = 0;
}
@@ -391,14 +391,14 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) {
// Process mesh tangents
if (pMesh->mTangents && ProcessArray(pMesh->mTangents, pMesh->mNumVertices, "tangents", dirtyMask)) {
delete[] pMesh->mBitangents;
pMesh->mBitangents = NULL;
pMesh->mBitangents = nullptr;
ret = true;
}
// Process mesh bitangents
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents, pMesh->mNumVertices, "bitangents", dirtyMask)) {
delete[] pMesh->mTangents;
pMesh->mTangents = NULL;
pMesh->mTangents = nullptr;
ret = true;
}
}

View File

@@ -45,41 +45,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* normals for all imported faces.
*/
#include "GenFaceNormalsProcess.h"
#include <assimp/Exceptional.h>
#include <assimp/postprocess.h>
#include <assimp/qnan.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exceptional.h>
#include <assimp/qnan.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
GenFaceNormalsProcess::GenFaceNormalsProcess()
{
GenFaceNormalsProcess::GenFaceNormalsProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
GenFaceNormalsProcess::~GenFaceNormalsProcess()
{
GenFaceNormalsProcess::~GenFaceNormalsProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenNormals) != 0;
return (pFlags & aiProcess_GenNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenFaceNormalsProcess::Execute( aiScene* pScene) {
void GenFaceNormalsProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin");
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
@@ -87,33 +83,35 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) {
}
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if(this->GenMeshFaceNormals( pScene->mMeshes[a])) {
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if (this->GenMeshFaceNormals(pScene->mMeshes[a])) {
bHas = true;
}
}
if (bHas) {
if (bHas) {
ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. "
"Face normals have been calculated");
"Face normals have been calculated");
} else {
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. "
"Normals are already there");
"Normals are already there");
}
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
{
if (NULL != pMesh->mNormals) {
if (force_) delete[] pMesh->mNormals;
else return false;
bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
if (nullptr != pMesh->mNormals) {
if (force_) {
delete[] pMesh->mNormals;
} else {
return false;
}
}
// If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors
// are undefined.
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
return false;
}
@@ -123,22 +121,22 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
const float qnan = get_qnan();
// iterate through all faces and compute per-face normals but store them per-vertex.
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace& face = pMesh->mFaces[a];
if (face.mNumIndices < 3) {
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace &face = pMesh->mFaces[a];
if (face.mNumIndices < 3) {
// either a point or a line -> no well-defined normal vector
for (unsigned int i = 0;i < face.mNumIndices;++i) {
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
}
continue;
}
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) {
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
pMesh->mNormals[face.mIndices[i]] = vNor;
}
}

View File

@@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* normals for all imported faces.
*/
// internal headers
#include "GenVertexNormalsProcess.h"
#include "ProcessHelper.h"
@@ -57,8 +55,8 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
GenVertexNormalsProcess::GenVertexNormalsProcess()
: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) {
GenVertexNormalsProcess::GenVertexNormalsProcess() :
configMaxAngle(AI_DEG_TO_RAD(175.f)) {
// empty
}
@@ -70,25 +68,22 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
{
bool GenVertexNormalsProcess::IsActive(unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenSmoothNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
{
void GenVertexNormalsProcess::SetupProperties(const Importer *pImp) {
// Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0);
configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0));
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, (ai_real)175.0);
configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle, (ai_real)175.0), (ai_real)0.0));
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::Execute( aiScene* pScene)
{
void GenVertexNormalsProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
@@ -96,34 +91,34 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
}
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
if(GenMeshVertexNormals( pScene->mMeshes[a],a))
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
if (GenMeshVertexNormals(pScene->mMeshes[a], a))
bHas = true;
}
if (bHas) {
if (bHas) {
ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
"Vertex normals have been calculated");
"Vertex normals have been calculated");
} else {
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
"Normals are already there");
"Normals are already there");
}
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
{
if (NULL != pMesh->mNormals) {
if (force_) delete[] pMesh->mNormals;
else return false;
bool GenVertexNormalsProcess::GenMeshVertexNormals(aiMesh *pMesh, unsigned int meshIndex) {
if (nullptr != pMesh->mNormals) {
if (force_)
delete[] pMesh->mNormals;
else
return false;
}
// If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors
// are undefined.
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
{
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
return false;
}
@@ -133,75 +128,71 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
// Compute per-face normals but store them per-vertex
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
const aiFace& face = pMesh->mFaces[a];
if (face.mNumIndices < 3)
{
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace &face = pMesh->mFaces[a];
if (face.mNumIndices < 3) {
// either a point or a line -> no normal vector
for (unsigned int i = 0;i < face.mNumIndices;++i) {
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
}
continue;
}
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) {
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
pMesh->mNormals[face.mIndices[i]] = vNor;
}
}
// Set up a SpatialSort to quickly find all vertices close to a given position
// check whether we can reuse the SpatialSort of a previous step.
SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder;
ai_real posEpsilon = ai_real( 1e-5 );
SpatialSort *vertexFinder = nullptr;
SpatialSort _vertexFinder;
ai_real posEpsilon = ai_real(1e-5);
if (shared) {
std::vector<std::pair<SpatialSort,ai_real> >* avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
if (avf)
{
std::pair<SpatialSort,ai_real>& blubb = avf->operator [] (meshIndex);
std::vector<std::pair<SpatialSort, ai_real>> *avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
if (avf) {
std::pair<SpatialSort, ai_real> &blubb = avf->operator[](meshIndex);
vertexFinder = &blubb.first;
posEpsilon = blubb.second;
}
}
if (!vertexFinder) {
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
if (!vertexFinder) {
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
vertexFinder = &_vertexFinder;
posEpsilon = ComputePositionEpsilon(pMesh);
}
std::vector<unsigned int> verticesFound;
aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
aiVector3D *pcNew = new aiVector3D[pMesh->mNumVertices];
if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
if (configMaxAngle >= AI_DEG_TO_RAD(175.f)) {
// There is no angle limit. Thus all vertices with positions close
// to each other will receive the same vertex normal. This allows us
// to optimize the whole algorithm a little bit ...
std::vector<bool> abHad(pMesh->mNumVertices,false);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
std::vector<bool> abHad(pMesh->mNumVertices, false);
for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
if (abHad[i]) {
continue;
}
// Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
if (is_not_qnan(v.x))pcNor += v;
const aiVector3D &v = pMesh->mNormals[verticesFound[a]];
if (is_not_qnan(v.x)) pcNor += v;
}
pcNor.NormalizeSafe();
// Write the smoothed normal back to all affected normals
for (unsigned int a = 0; a < verticesFound.size(); ++a)
{
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
unsigned int vidx = verticesFound[a];
pcNew[vidx] = pcNor;
abHad[vidx] = true;
@@ -210,11 +201,11 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
}
// Slower code path if a smooth angle is set. There are many ways to achieve
// the effect, this one is the most straightforward one.
else {
else {
const ai_real fLimit = std::cos(configMaxAngle);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
// Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
aiVector3D vr = pMesh->mNormals[i];

View File

@@ -355,7 +355,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
// very intense verbose logging ... prepare for much text if there are many meshes
if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
ASSIMP_LOG_VERBOSE_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
}
fACMR2 *= pMesh->mNumFaces;

View File

@@ -266,7 +266,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
// float posEpsilonSqr;
SpatialSort* vertexFinder = NULL;
SpatialSort *vertexFinder = nullptr;
SpatialSort _vertexFinder;
typedef std::pair<SpatialSort,float> SpatPair;
@@ -373,7 +373,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
}
if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
ASSIMP_LOG_DEBUG_F(
ASSIMP_LOG_VERBOSE_DEBUG_F(
"Mesh ",meshIndex,
" (",
(pMesh->mName.length ? pMesh->mName.data : "unnamed"),
@@ -408,7 +408,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
std::vector<aiVertexWeight> newWeights;
newWeights.reserve( bone->mNumWeights);
if ( NULL != bone->mWeights ) {
if (nullptr != bone->mWeights) {
for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) {
const aiVertexWeight& ow = bone->mWeights[ b ];
// if the vertex is a unique one, translate it
@@ -420,7 +420,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
}
}
} else {
ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is nullptr." );
}
if (newWeights.size() > 0) {

View File

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LimitBoneWeightsProcess.h"
#include <assimp/SmallVector.h>
#include <assimp/StringUtils.h>
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
@@ -52,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess()
@@ -76,10 +76,12 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
void LimitBoneWeightsProcess::Execute( aiScene* pScene)
{
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
ProcessMesh(pScene->mMeshes[a]);
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
ProcessMesh(pScene->mMeshes[m]);
}
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
@@ -95,107 +97,100 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
{
if( !pMesh->HasBones())
if (!pMesh->HasBones())
return;
// collect all bone weights per vertex
typedef std::vector< std::vector< Weight > > WeightsPerVertex;
WeightsPerVertex vertexWeights( pMesh->mNumVertices);
typedef SmallVector<Weight,8> VertexWeightArray;
typedef std::vector<VertexWeightArray> WeightsPerVertex;
WeightsPerVertex vertexWeights(pMesh->mNumVertices);
size_t maxVertexWeights = 0;
// collect all weights per vertex
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
for (unsigned int b = 0; b < pMesh->mNumBones; ++b)
{
const aiBone* bone = pMesh->mBones[a];
for( unsigned int b = 0; b < bone->mNumWeights; b++)
const aiBone* bone = pMesh->mBones[b];
for (unsigned int w = 0; w < bone->mNumWeights; ++w)
{
const aiVertexWeight& w = bone->mWeights[b];
vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
const aiVertexWeight& vw = bone->mWeights[w];
if (vertexWeights.size() <= vw.mVertexId)
continue;
vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight));
maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size());
}
}
if (maxVertexWeights <= mMaxWeights)
return;
unsigned int removed = 0, old_bones = pMesh->mNumBones;
// now cut the weight count if it exceeds the maximum
bool bChanged = false;
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;
bChanged = true;
// more than the defined maximum -> first sort by weight in descending order. That's
// why we defined the < operator in such a weird way.
std::sort( vit->begin(), vit->end());
std::sort(vit->begin(), vit->end());
// now kill everything beyond the maximum count
unsigned int m = static_cast<unsigned int>(vit->size());
vit->erase( vit->begin() + mMaxWeights, vit->end());
removed += static_cast<unsigned int>(m-vit->size());
vit->resize(mMaxWeights);
removed += static_cast<unsigned int>(m - vit->size());
// and renormalize the weights
float sum = 0.0f;
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
for(const Weight* it = vit->begin(); it != vit->end(); ++it) {
sum += it->mWeight;
}
if( 0.0f != sum ) {
if (0.0f != sum) {
const float invSum = 1.0f / sum;
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
for(Weight* it = vit->begin(); it != vit->end(); ++it) {
it->mWeight *= invSum;
}
}
}
if (bChanged) {
// rebuild the vertex weight array for all bones
typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
WeightsPerBone boneWeights( pMesh->mNumBones);
for( unsigned int a = 0; a < vertexWeights.size(); a++)
// clear weight count for all bone
for (unsigned int a = 0; a < pMesh->mNumBones; ++a)
{
pMesh->mBones[a]->mNumWeights = 0;
}
// rebuild the vertex weight array for all bones
for (unsigned int a = 0; a < vertexWeights.size(); ++a)
{
const VertexWeightArray& vw = vertexWeights[a];
for (const Weight* it = vw.begin(); it != vw.end(); ++it)
{
const std::vector<Weight>& vw = vertexWeights[a];
for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
}
// and finally copy the vertex weight list over to the mesh's bones
std::vector<bool> abNoNeed(pMesh->mNumBones,false);
bChanged = false;
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
{
const std::vector<aiVertexWeight>& bw = boneWeights[a];
aiBone* bone = pMesh->mBones[a];
if ( bw.empty() )
{
abNoNeed[a] = bChanged = true;
continue;
}
// copy the weight list. should always be less weights than before, so we don't need a new allocation
ai_assert( bw.size() <= bone->mNumWeights);
bone->mNumWeights = static_cast<unsigned int>( bw.size() );
::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
}
if (bChanged) {
// the number of new bones is smaller than before, so we can reuse the old array
aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
if (*iter) {
delete *ppcSrc;
--pMesh->mNumBones;
}
else *ppcCur++ = *ppcSrc;
++ppcSrc;
}
}
if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
aiBone* bone = pMesh->mBones[it->mBone];
bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
}
}
// remove empty bones
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;
}
}
pMesh->mNumBones = writeBone;
if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
}
}

View File

@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the post processing step "MakeVerboseFormat"
*/
#include "MakeVerboseFormat.h"
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
@@ -51,26 +50,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{
MakeVerboseFormatProcess::MakeVerboseFormatProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{
MakeVerboseFormatProcess::~MakeVerboseFormatProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{
ai_assert(NULL != pScene);
void MakeVerboseFormatProcess::Execute(aiScene *pScene) {
ai_assert(nullptr != pScene);
ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
{
if( MakeVerboseFormat( pScene->mMeshes[a]))
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if (MakeVerboseFormat(pScene->mMeshes[a]))
bHas = true;
}
if (bHas) {
@@ -84,29 +79,26 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{
ai_assert(NULL != pcMesh);
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh *pcMesh) {
ai_assert(nullptr != pcMesh);
unsigned int iOldNumVertices = pcMesh->mNumVertices;
const unsigned int iNumVerts = pcMesh->mNumFaces*3;
const unsigned int iNumVerts = pcMesh->mNumFaces * 3;
aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];
aiVector3D *pvPositions = new aiVector3D[iNumVerts];
aiVector3D* pvNormals = NULL;
if (pcMesh->HasNormals())
{
aiVector3D *pvNormals = nullptr;
if (pcMesh->HasNormals()) {
pvNormals = new aiVector3D[iNumVerts];
}
aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
if (pcMesh->HasTangentsAndBitangents())
{
aiVector3D *pvTangents = nullptr, *pvBitangents = nullptr;
if (pcMesh->HasTangentsAndBitangents()) {
pvTangents = new aiVector3D[iNumVerts];
pvBitangents = new aiVector3D[iNumVerts];
}
aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};
aiVector3D *apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = { 0 };
aiColor4D *apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = { 0 };
unsigned int p = 0;
while (pcMesh->HasTextureCoords(p))
@@ -117,24 +109,21 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
apvColorSets[p++] = new aiColor4D[iNumVerts];
// allocate enough memory to hold output bones and vertex weights ...
std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
std::vector<aiVertexWeight> *newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights * 3);
}
// iterate through all faces and build a clean list
unsigned int iIndex = 0;
for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
{
aiFace* pcFace = &pcMesh->mFaces[a];
for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
{
for (unsigned int a = 0; a < pcMesh->mNumFaces; ++a) {
aiFace *pcFace = &pcMesh->mFaces[a];
for (unsigned int q = 0; q < pcFace->mNumIndices; ++q, ++iIndex) {
// need to build a clean list of bones, too
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) {
const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx];
if(pcFace->mIndices[q] == w.mVertexId) {
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) {
const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx];
if (pcFace->mIndices[q] == w.mVertexId) {
aiVertexWeight wNew;
wNew.mVertexId = iIndex;
wNew.mWeight = w.mWeight;
@@ -145,45 +134,38 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
if (pcMesh->HasNormals())
{
if (pcMesh->HasNormals()) {
pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
}
if (pcMesh->HasTangentsAndBitangents())
{
if (pcMesh->HasTangentsAndBitangents()) {
pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
}
unsigned int pp = 0;
while (pcMesh->HasTextureCoords(pp))
{
apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]];
++pp;
while (pcMesh->HasTextureCoords(pp)) {
apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]];
++pp;
}
pp = 0;
while (pcMesh->HasVertexColors(pp))
{
apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]];
++pp;
pp = 0;
while (pcMesh->HasVertexColors(pp)) {
apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]];
++pp;
}
pcFace->mIndices[q] = iIndex;
}
}
// build output vertex weights
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
delete [] pcMesh->mBones[i]->mWeights;
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
delete[] pcMesh->mBones[i]->mWeights;
if (!newWeights[i].empty()) {
pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
aiVertexWeight *weightToCopy = &( newWeights[i][0] );
aiVertexWeight *weightToCopy = &(newWeights[i][0]);
memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
sizeof(aiVertexWeight) * newWeights[i].size());
sizeof(aiVertexWeight) * newWeights[i].size());
} else {
pcMesh->mBones[i]->mWeights = NULL;
pcMesh->mBones[i]->mWeights = nullptr;
}
}
delete[] newWeights;
@@ -193,28 +175,24 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
pcMesh->mVertices = pvPositions;
p = 0;
while (pcMesh->HasTextureCoords(p))
{
while (pcMesh->HasTextureCoords(p)) {
delete[] pcMesh->mTextureCoords[p];
pcMesh->mTextureCoords[p] = apvTextureCoords[p];
++p;
}
p = 0;
while (pcMesh->HasVertexColors(p))
{
while (pcMesh->HasVertexColors(p)) {
delete[] pcMesh->mColors[p];
pcMesh->mColors[p] = apvColorSets[p];
++p;
}
pcMesh->mNumVertices = iNumVerts;
if (pcMesh->HasNormals())
{
if (pcMesh->HasNormals()) {
delete[] pcMesh->mNormals;
pcMesh->mNormals = pvNormals;
}
if (pcMesh->HasTangentsAndBitangents())
{
if (pcMesh->HasTangentsAndBitangents()) {
delete[] pcMesh->mTangents;
pcMesh->mTangents = pvTangents;
delete[] pcMesh->mBitangents;
@@ -223,15 +201,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
return (pcMesh->mNumVertices != iOldNumVertices);
}
// ------------------------------------------------------------------------------------------------
bool IsMeshInVerboseFormat(const aiMesh* mesh) {
bool IsMeshInVerboseFormat(const aiMesh *mesh) {
// avoid slow vector<bool> specialization
std::vector<unsigned int> seen(mesh->mNumVertices,0);
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
const aiFace& f = mesh->mFaces[i];
for(unsigned int j = 0; j < f.mNumIndices; ++j) {
if(++seen[f.mIndices[j]] == 2) {
std::vector<unsigned int> seen(mesh->mNumVertices, 0);
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
const aiFace &f = mesh->mFaces[i];
for (unsigned int j = 0; j < f.mNumIndices; ++j) {
if (++seen[f.mIndices[j]] == 2) {
// found a duplicate index
return false;
}
@@ -242,9 +219,9 @@ bool IsMeshInVerboseFormat(const aiMesh* mesh) {
}
// ------------------------------------------------------------------------------------------------
bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene* pScene) {
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
if(!IsMeshInVerboseFormat(pScene->mMeshes[i])) {
bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene *pScene) {
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
if (!IsMeshInVerboseFormat(pScene->mMeshes[i])) {
return false;
}
}

View File

@@ -445,7 +445,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
delete mesh->mBones[a];
delete[] mesh->mBones;
mesh->mBones = NULL;
mesh->mBones = nullptr;
}
// now build a list of output meshes
@@ -472,12 +472,12 @@ void PretransformVertices::Execute(aiScene *pScene) {
pScene->mMeshes = npp;
}
// now iterate through all meshes and transform them to worldspace
// now iterate through all meshes and transform them to world-space
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
ApplyTransform(pScene->mMeshes[i], *reinterpret_cast<aiMatrix4x4 *>(pScene->mMeshes[i]->mBones));
// prevent improper destruction
pScene->mMeshes[i]->mBones = NULL;
pScene->mMeshes[i]->mBones = nullptr;
pScene->mMeshes[i]->mNumBones = 0;
}
} else {
@@ -539,22 +539,22 @@ void PretransformVertices::Execute(aiScene *pScene) {
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiMesh *mesh = pScene->mMeshes[i];
mesh->mNumBones = 0;
mesh->mBones = NULL;
mesh->mBones = nullptr;
// we're reusing the face index arrays. avoid destruction
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
mesh->mFaces[a].mNumIndices = 0;
mesh->mFaces[a].mIndices = NULL;
mesh->mFaces[a].mIndices = nullptr;
}
delete mesh;
// Invalidate the contents of the old mesh array. We will most
// likely have less output meshes now, so the last entries of
// the mesh array are not overridden. We set them to NULL to
// the mesh array are not overridden. We set them to nullptr to
// make sure the developer gets notified when his application
// attempts to access these fields ...
mesh = NULL;
mesh = nullptr;
}
// It is impossible that we have more output meshes than
@@ -571,14 +571,14 @@ void PretransformVertices::Execute(aiScene *pScene) {
delete pScene->mAnimations[i];
delete[] pScene->mAnimations;
pScene->mAnimations = NULL;
pScene->mAnimations = nullptr;
pScene->mNumAnimations = 0;
// --- we need to keep all cameras and lights
for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
aiCamera *cam = pScene->mCameras[i];
const aiNode *nd = pScene->mRootNode->FindNode(cam->mName);
ai_assert(NULL != nd);
ai_assert(nullptr != nd);
// multiply all properties of the camera with the absolute
// transformation of the corresponding node
@@ -590,7 +590,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
aiLight *l = pScene->mLights[i];
const aiNode *nd = pScene->mRootNode->FindNode(l->mName);
ai_assert(NULL != nd);
ai_assert(nullptr != nd);
// multiply all properties of the camera with the absolute
// transformation of the corresponding node

View File

@@ -43,22 +43,19 @@ 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 <limits>
namespace Assimp {
// -------------------------------------------------------------------------------
void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
{
const char* s = in.c_str();
void ConvertListToStrings(const std::string &in, std::list<std::string> &out) {
const char *s = in.c_str();
while (*s) {
SkipSpacesAndLineEnd(&s);
if (*s == '\'') {
const char* base = ++s;
const char *base = ++s;
while (*s != '\'') {
++s;
if (*s == '\0') {
@@ -66,43 +63,39 @@ void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
return;
}
}
out.push_back(std::string(base,(size_t)(s-base)));
out.push_back(std::string(base, (size_t)(s - base)));
++s;
}
else {
} 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)
{
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);
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 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 ( NULL == scene ) {
void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max) {
if (nullptr == scene) {
return;
}
if ( 0 == scene->mNumMeshes ) {
if (0 == scene->mNumMeshes) {
return;
}
FindMeshCenter(scene->mMeshes[0], out, min, max);
@@ -116,79 +109,71 @@ void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector
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;
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, aiVector3D &min,
aiVector3D &max, const aiMatrix4x4 &m) {
FindAABBTransformed(mesh, min, max, m);
out = min + (max - min) * (ai_real)0.5;
}
// -------------------------------------------------------------------------------
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,
const aiMatrix4x4& m)
{
aiVector3D min,max;
FindMeshCenterTransformed(mesh,out,min,max,m);
void FindMeshCenter(aiMesh *mesh, aiVector3D &out) {
aiVector3D min, max;
FindMeshCenter(mesh, out, min, max);
}
// -------------------------------------------------------------------------------
ai_real ComputePositionEpsilon(const aiMesh* pMesh)
{
const ai_real epsilon = ai_real( 1e-4 );
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);
ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, minVec, maxVec);
return (maxVec - minVec).Length() * epsilon;
}
// -------------------------------------------------------------------------------
ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
{
ai_assert( NULL != pMeshes );
ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num) {
ai_assert(nullptr != pMeshes);
const ai_real epsilon = ai_real( 1e-4 );
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<aiVector3D>()(minVec,maxVec);
MinMaxChooser<aiVector3D>()(minVec, maxVec);
for (size_t a = 0; a < num; ++a) {
const aiMesh* pMesh = pMeshes[a];
ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma);
const aiMesh *pMesh = pMeshes[a];
ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, mi, ma);
minVec = std::min(minVec,mi);
maxVec = std::max(maxVec,ma);
minVec = std::min(minVec, mi);
maxVec = std::max(maxVec, ma);
}
return (maxVec - minVec).Length() * epsilon;
}
// -------------------------------------------------------------------------------
unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
{
ai_assert(NULL != pcMesh);
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;
if (pcMesh->HasNormals()) iRet |= 0x2;
// tangents and bitangents
if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4;
#ifdef BOOST_STATIC_ASSERT
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
@@ -197,8 +182,7 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
// texture coordinates
unsigned int p = 0;
while (pcMesh->HasTextureCoords(p))
{
while (pcMesh->HasTextureCoords(p)) {
iRet |= (0x100 << p);
if (3 == pcMesh->mNumUVComponents[p])
iRet |= (0x10000 << p);
@@ -207,34 +191,32 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
}
// vertex colors
p = 0;
while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
while (pcMesh->HasVertexColors(p))
iRet |= (0x1000000 << p++);
return iRet;
}
// -------------------------------------------------------------------------------
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh)
{
VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh) {
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
return NULL;
return nullptr;
}
VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
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<unsigned int,float>(i,weight.mWeight) );
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<unsigned int, float>(i, weight.mWeight));
}
}
return avPerVertexWeights;
}
// -------------------------------------------------------------------------------
const char* MappingTypeToString(aiTextureMapping in)
{
switch (in)
{
const char *MappingTypeToString(aiTextureMapping in) {
switch (in) {
case aiTextureMapping_UV:
return "UV";
case aiTextureMapping_BOX:
@@ -252,24 +234,22 @@ const char* MappingTypeToString(aiTextureMapping in)
}
ai_assert(false);
return "BUG";
return "BUG";
}
// -------------------------------------------------------------------------------
aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags)
{
aiMesh *MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags) {
aiMesh *oMesh = new aiMesh();
std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);
std::vector<unsigned int> vMap(pMesh->mNumVertices, UINT_MAX);
size_t numSubVerts = 0;
size_t numSubFaces = subMeshFaces.size();
for(unsigned int i=0;i<numSubFaces;i++) {
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) {
for (unsigned int j = 0; j < f.mNumIndices; j++) {
if (vMap[f.mIndices[j]] == UINT_MAX) {
vMap[f.mIndices[j]] = static_cast<unsigned int>(numSubVerts++);
}
}
@@ -285,114 +265,114 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMes
oMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
oMesh->mNumVertices = static_cast<unsigned int>(numSubVerts);
oMesh->mVertices = new aiVector3D[numSubVerts];
if( pMesh->HasNormals() ) {
if (pMesh->HasNormals()) {
oMesh->mNormals = new aiVector3D[numSubVerts];
}
if( pMesh->HasTangentsAndBitangents() ) {
if (pMesh->HasTangentsAndBitangents()) {
oMesh->mTangents = new aiVector3D[numSubVerts];
oMesh->mBitangents = new aiVector3D[numSubVerts];
}
for( size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)) ; ++a ) {
for (size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)); ++a) {
oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
}
for( size_t a = 0; pMesh->HasVertexColors( static_cast<unsigned int>(a)); ++a ) {
for (size_t a = 0; pMesh->HasVertexColors(static_cast<unsigned int>(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 ) {
for (unsigned int a = 0; a < numSubFaces; ++a) {
const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
aiFace& dstFace = oMesh->mFaces[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 ) {
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 ) {
for (unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex) {
unsigned int nvi = vMap[srcIndex];
if(nvi==UINT_MAX) {
if (nvi == UINT_MAX) {
continue;
}
oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
if( pMesh->HasNormals() ) {
if (pMesh->HasNormals()) {
oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
}
if( pMesh->HasTangentsAndBitangents() ) {
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->GetNumUVChannels(); c < cc; ++c) {
oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
}
for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) {
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<unsigned int> subBones(pMesh->mNumBones,0);
if (~subFlags & AI_SUBMESH_FLAGS_SANS_BONES) {
std::vector<unsigned int> subBones(pMesh->mNumBones, 0);
for(unsigned int a=0;a<pMesh->mNumBones;++a) {
const aiBone* bone = pMesh->mBones[a];
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
const aiBone *bone = pMesh->mBones[a];
for(unsigned int b=0;b<bone->mNumWeights;b++) {
for (unsigned int b = 0; b < bone->mNumWeights; b++) {
unsigned int v = vMap[bone->mWeights[b].mVertexId];
if(v!=UINT_MAX) {
if (v != UINT_MAX) {
subBones[a]++;
}
}
}
for(unsigned int a=0;a<pMesh->mNumBones;++a) {
if(subBones[a]>0) {
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
if (subBones[a] > 0) {
oMesh->mNumBones++;
}
}
if(oMesh->mNumBones) {
oMesh->mBones = new aiBone*[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) {
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];
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++) {
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);
if (v != UINT_MAX) {
aiVertexWeight w(v, bone->mWeights[b].mWeight);
newBone->mWeights[newBone->mNumWeights++] = w;
}
}
}
ai_assert(nbParanoia==oMesh->mNumBones);
ai_assert(nbParanoia == oMesh->mNumBones);
(void)nbParanoia; // remove compiler warning on release build
}
}

View File

@@ -43,16 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_PROCESS_HELPER_H_INCLUDED
#define AI_PROCESS_HELPER_H_INCLUDED
#include <assimp/postprocess.h>
#include <assimp/anim.h>
#include <assimp/mesh.h>
#include <assimp/material.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/SpatialSort.h>
#include "Common/BaseProcess.h"
#include <assimp/ParsingUtils.h>
#include <assimp/SpatialSort.h>
#include <list>
@@ -63,86 +63,83 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
namespace std {
// std::min for aiVector3D
template <typename TReal>
inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
}
// std::min for aiVector3D
template <typename TReal>
inline ::aiVector3t<TReal> min(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
return ::aiVector3t<TReal>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
}
// std::max for aiVector3t<TReal>
template <typename TReal>
inline ::aiVector3t<TReal> max (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
return ::aiVector3t<TReal> (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
}
// std::max for aiVector3t<TReal>
template <typename TReal>
inline ::aiVector3t<TReal> max(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
return ::aiVector3t<TReal>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
}
// std::min for aiVector2t<TReal>
template <typename TReal>
inline ::aiVector2t<TReal> min (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
return ::aiVector2t<TReal> (min(a.x,b.x),min(a.y,b.y));
}
// std::min for aiVector2t<TReal>
template <typename TReal>
inline ::aiVector2t<TReal> min(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
return ::aiVector2t<TReal>(min(a.x, b.x), min(a.y, b.y));
}
// std::max for aiVector2t<TReal>
template <typename TReal>
inline ::aiVector2t<TReal> max (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
return ::aiVector2t<TReal> (max(a.x,b.x),max(a.y,b.y));
}
// std::max for aiVector2t<TReal>
template <typename TReal>
inline ::aiVector2t<TReal> max(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
return ::aiVector2t<TReal>(max(a.x, b.x), max(a.y, b.y));
}
// std::min for aiColor4D
template <typename TReal>
inline ::aiColor4t<TReal> min (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
return ::aiColor4t<TReal> (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a));
}
// std::min for aiColor4D
template <typename TReal>
inline ::aiColor4t<TReal> min(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
return ::aiColor4t<TReal>(min(a.r, b.r), min(a.g, b.g), min(a.b, b.b), min(a.a, b.a));
}
// std::max for aiColor4D
template <typename TReal>
inline ::aiColor4t<TReal> max (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
return ::aiColor4t<TReal> (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a));
}
// std::max for aiColor4D
template <typename TReal>
inline ::aiColor4t<TReal> max(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
return ::aiColor4t<TReal>(max(a.r, b.r), max(a.g, b.g), max(a.b, b.b), max(a.a, b.a));
}
// std::min for aiQuaterniont<TReal>
template <typename TReal>
inline ::aiQuaterniont<TReal> min(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
return ::aiQuaterniont<TReal>(min(a.w, b.w), min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
}
// std::min for aiQuaterniont<TReal>
template <typename TReal>
inline ::aiQuaterniont<TReal> min (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
return ::aiQuaterniont<TReal> (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
}
// std::max for aiQuaterniont<TReal>
template <typename TReal>
inline ::aiQuaterniont<TReal> max(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
return ::aiQuaterniont<TReal>(max(a.w, b.w), max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
}
// std::max for aiQuaterniont<TReal>
template <typename TReal>
inline ::aiQuaterniont<TReal> max (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
return ::aiQuaterniont<TReal> (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
}
// std::min for aiVectorKey
inline ::aiVectorKey min(const ::aiVectorKey &a, const ::aiVectorKey &b) {
return ::aiVectorKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
}
// std::max for aiVectorKey
inline ::aiVectorKey max(const ::aiVectorKey &a, const ::aiVectorKey &b) {
return ::aiVectorKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
}
// std::min for aiQuatKey
inline ::aiQuatKey min(const ::aiQuatKey &a, const ::aiQuatKey &b) {
return ::aiQuatKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
}
// std::min for aiVectorKey
inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) {
return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
}
// std::max for aiQuatKey
inline ::aiQuatKey max(const ::aiQuatKey &a, const ::aiQuatKey &b) {
return ::aiQuatKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
}
// std::max for aiVectorKey
inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) {
return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
}
// std::min for aiVertexWeight
inline ::aiVertexWeight min(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
return ::aiVertexWeight(min(a.mVertexId, b.mVertexId), min(a.mWeight, b.mWeight));
}
// std::min for aiQuatKey
inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) {
return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
}
// std::max for aiQuatKey
inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) {
return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
}
// std::min for aiVertexWeight
inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight));
}
// std::max for aiVertexWeight
inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight));
}
// std::max for aiVertexWeight
inline ::aiVertexWeight max(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
return ::aiVertexWeight(max(a.mVertexId, b.mVertexId), max(a.mWeight, b.mWeight));
}
} // end namespace std
#endif // !! C++
@@ -154,60 +151,80 @@ namespace Assimp {
template <typename T>
struct MinMaxChooser;
template <> struct MinMaxChooser<float> {
void operator ()(float& min,float& max) {
template <>
struct MinMaxChooser<float> {
void operator()(float &min, float &max) {
max = -1e10f;
min = 1e10f;
}};
template <> struct MinMaxChooser<double> {
void operator ()(double& min,double& max) {
min = 1e10f;
}
};
template <>
struct MinMaxChooser<double> {
void operator()(double &min, double &max) {
max = -1e10;
min = 1e10;
}};
template <> struct MinMaxChooser<unsigned int> {
void operator ()(unsigned int& min,unsigned int& max) {
min = 1e10;
}
};
template <>
struct MinMaxChooser<unsigned int> {
void operator()(unsigned int &min, unsigned int &max) {
max = 0;
min = (1u<<(sizeof(unsigned int)*8-1));
}};
min = (1u << (sizeof(unsigned int) * 8 - 1));
}
};
template <typename T> struct MinMaxChooser< aiVector3t<T> > {
void operator ()(aiVector3t<T>& min,aiVector3t<T>& max) {
max = aiVector3t<T>(-1e10f,-1e10f,-1e10f);
min = aiVector3t<T>( 1e10f, 1e10f, 1e10f);
}};
template <typename T> struct MinMaxChooser< aiVector2t<T> > {
void operator ()(aiVector2t<T>& min,aiVector2t<T>& max) {
max = aiVector2t<T>(-1e10f,-1e10f);
min = aiVector2t<T>( 1e10f, 1e10f);
}};
template <typename T> struct MinMaxChooser< aiColor4t<T> > {
void operator ()(aiColor4t<T>& min,aiColor4t<T>& max) {
max = aiColor4t<T>(-1e10f,-1e10f,-1e10f,-1e10f);
min = aiColor4t<T>( 1e10f, 1e10f, 1e10f, 1e10f);
}};
template <typename T>
struct MinMaxChooser<aiVector3t<T>> {
void operator()(aiVector3t<T> &min, aiVector3t<T> &max) {
max = aiVector3t<T>(-1e10f, -1e10f, -1e10f);
min = aiVector3t<T>(1e10f, 1e10f, 1e10f);
}
};
template <typename T>
struct MinMaxChooser<aiVector2t<T>> {
void operator()(aiVector2t<T> &min, aiVector2t<T> &max) {
max = aiVector2t<T>(-1e10f, -1e10f);
min = aiVector2t<T>(1e10f, 1e10f);
}
};
template <typename T>
struct MinMaxChooser<aiColor4t<T>> {
void operator()(aiColor4t<T> &min, aiColor4t<T> &max) {
max = aiColor4t<T>(-1e10f, -1e10f, -1e10f, -1e10f);
min = aiColor4t<T>(1e10f, 1e10f, 1e10f, 1e10f);
}
};
template <typename T> struct MinMaxChooser< aiQuaterniont<T> > {
void operator ()(aiQuaterniont<T>& min,aiQuaterniont<T>& max) {
max = aiQuaterniont<T>(-1e10f,-1e10f,-1e10f,-1e10f);
min = aiQuaterniont<T>( 1e10f, 1e10f, 1e10f, 1e10f);
}};
template <typename T>
struct MinMaxChooser<aiQuaterniont<T>> {
void operator()(aiQuaterniont<T> &min, aiQuaterniont<T> &max) {
max = aiQuaterniont<T>(-1e10f, -1e10f, -1e10f, -1e10f);
min = aiQuaterniont<T>(1e10f, 1e10f, 1e10f, 1e10f);
}
};
template <> struct MinMaxChooser<aiVectorKey> {
void operator ()(aiVectorKey& min,aiVectorKey& max) {
MinMaxChooser<double>()(min.mTime,max.mTime);
MinMaxChooser<aiVector3D>()(min.mValue,max.mValue);
}};
template <> struct MinMaxChooser<aiQuatKey> {
void operator ()(aiQuatKey& min,aiQuatKey& max) {
MinMaxChooser<double>()(min.mTime,max.mTime);
MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue);
}};
template <>
struct MinMaxChooser<aiVectorKey> {
void operator()(aiVectorKey &min, aiVectorKey &max) {
MinMaxChooser<double>()(min.mTime, max.mTime);
MinMaxChooser<aiVector3D>()(min.mValue, max.mValue);
}
};
template <>
struct MinMaxChooser<aiQuatKey> {
void operator()(aiQuatKey &min, aiQuatKey &max) {
MinMaxChooser<double>()(min.mTime, max.mTime);
MinMaxChooser<aiQuaternion>()(min.mValue, max.mValue);
}
};
template <> struct MinMaxChooser<aiVertexWeight> {
void operator ()(aiVertexWeight& min,aiVertexWeight& max) {
MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId);
MinMaxChooser<float>()(min.mWeight,max.mWeight);
}};
template <>
struct MinMaxChooser<aiVertexWeight> {
void operator()(aiVertexWeight &min, aiVertexWeight &max) {
MinMaxChooser<unsigned int>()(min.mVertexId, max.mVertexId);
MinMaxChooser<float>()(min.mWeight, max.mWeight);
}
};
// -------------------------------------------------------------------------------
/** @brief Find the min/max values of an array of Ts
@@ -217,36 +234,31 @@ template <> struct MinMaxChooser<aiVertexWeight> {
* @param[out] max maximum value
*/
template <typename T>
inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
{
MinMaxChooser<T> ()(min,max);
for (unsigned int i = 0; i < size;++i) {
min = std::min(in[i],min);
max = std::max(in[i],max);
inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) {
MinMaxChooser<T>()(min, max);
for (unsigned int i = 0; i < size; ++i) {
min = std::min(in[i], min);
max = std::max(in[i], max);
}
}
// -------------------------------------------------------------------------------
/** Little helper function to calculate the quadratic difference
* of two colours.
* @param pColor1 First color
* @param pColor2 second color
* @return Quadratic color difference */
inline ai_real GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
{
const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
inline ai_real GetColorDifference(const aiColor4D &pColor1, const aiColor4D &pColor2) {
const aiColor4D c(pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
}
// -------------------------------------------------------------------------------
/** @brief Extract single strings from a list of identifiers
* @param in Input string list.
* @param out Receives a list of clean output strings
* @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */
void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
void ConvertListToStrings(const std::string &in, std::list<std::string> &out);
// -------------------------------------------------------------------------------
/** @brief Compute the AABB of a mesh after applying a given transform
@@ -254,8 +266,7 @@ void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
* @param[out] min Receives minimum transformed vertex
* @param[out] max Receives maximum transformed vertex
* @param m Transformation matrix to be applied */
void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, const aiMatrix4x4& m);
void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
// -------------------------------------------------------------------------------
/** @brief Helper function to determine the 'real' center of a mesh
@@ -265,7 +276,7 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
* @param[out] min Minimum vertex of the mesh
* @param[out] max maximum vertex of the mesh
* @param[out] out Center point */
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max);
void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max);
// -------------------------------------------------------------------------------
/** @brief Helper function to determine the 'real' center of a scene
@@ -275,106 +286,90 @@ void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D&
* @param[out] min Minimum vertex of the scene
* @param[out] max maximum vertex of the scene
* @param[out] out Center point */
void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max);
void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max);
// -------------------------------------------------------------------------------
// Helper function to determine the 'real' center of a mesh after applying a given transform
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,aiVector3D& max, const aiMatrix4x4& m);
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
// -------------------------------------------------------------------------------
// Helper function to determine the 'real' center of a mesh
void FindMeshCenter (aiMesh* mesh, aiVector3D& out);
void FindMeshCenter(aiMesh *mesh, aiVector3D &out);
// -------------------------------------------------------------------------------
// Helper function to determine the 'real' center of a mesh after applying a given transform
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,const aiMatrix4x4& m);
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, const aiMatrix4x4 &m);
// -------------------------------------------------------------------------------
// Compute a good epsilon value for position comparisons on a mesh
ai_real ComputePositionEpsilon(const aiMesh* pMesh);
ai_real ComputePositionEpsilon(const aiMesh *pMesh);
// -------------------------------------------------------------------------------
// Compute a good epsilon value for position comparisons on a array of meshes
ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num);
ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num);
// -------------------------------------------------------------------------------
// Compute an unique value for the vertex format of a mesh
unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh);
unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh);
// defs for ComputeVertexBoneWeightTable()
typedef std::pair <unsigned int,float> PerVertexWeight;
typedef std::vector <PerVertexWeight> VertexWeightTable;
typedef std::pair<unsigned int, float> PerVertexWeight;
typedef std::vector<PerVertexWeight> VertexWeightTable;
// -------------------------------------------------------------------------------
// Compute a per-vertex bone weight table
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh);
VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh);
// -------------------------------------------------------------------------------
// Get a string for a given aiTextureMapping
const char* MappingTypeToString(aiTextureMapping in);
const char *MappingTypeToString(aiTextureMapping in);
// flags for MakeSubmesh()
#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
// -------------------------------------------------------------------------------
// Split a mesh given a list of faces to be contained in the sub mesh
aiMesh* MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
aiMesh *MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
// -------------------------------------------------------------------------------
// Utility postprocess step to share the spatial sort tree between
// all steps which use it to speedup its computations.
class ComputeSpatialSortProcess : public BaseProcess
{
bool IsActive( unsigned int pFlags) const
{
return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
class ComputeSpatialSortProcess : public BaseProcess {
bool IsActive(unsigned int pFlags) const {
return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
}
void Execute( aiScene* pScene)
{
void Execute(aiScene *pScene) {
typedef std::pair<SpatialSort, ai_real> _Type;
ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache");
std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
std::vector<_Type> *p = new std::vector<_Type>(pScene->mNumMeshes);
std::vector<_Type>::iterator it = p->begin();
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
aiMesh* mesh = pScene->mMeshes[i];
_Type& blubb = *it;
blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
aiMesh *mesh = pScene->mMeshes[i];
_Type &blubb = *it;
blubb.first.Fill(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D));
blubb.second = ComputePositionEpsilon(mesh);
}
shared->AddProperty(AI_SPP_SPATIAL_SORT,p);
shared->AddProperty(AI_SPP_SPATIAL_SORT, p);
}
};
// -------------------------------------------------------------------------------
// ... and the same again to cleanup the whole stuff
class DestroySpatialSortProcess : public BaseProcess
{
bool IsActive( unsigned int pFlags) const
{
return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
class DestroySpatialSortProcess : public BaseProcess {
bool IsActive(unsigned int pFlags) const {
return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
}
void Execute( aiScene* /*pScene*/)
{
void Execute(aiScene * /*pScene*/) {
shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
}
};
} // ! namespace Assimp
} // namespace Assimp
#endif // !! AI_PROCESS_HELPER_H_INCLUDED

View File

@@ -122,7 +122,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
// Keep this material even if no mesh references it
abReferenced[i] = true;
ASSIMP_LOG_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'");
ASSIMP_LOG_VERBOSE_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'");
}
}
}
@@ -197,7 +197,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
// update all material indices
for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
aiMesh* mesh = pScene->mMeshes[p];
ai_assert( NULL!=mesh );
ai_assert(nullptr != mesh);
mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
}
// delete the old material list

View File

@@ -44,43 +44,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* any parts of the mesh structure from the imported data.
*/
#include "RemoveVCProcess.h"
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RemoveVCProcess::RemoveVCProcess() :
configDeleteFlags()
, mScene()
{}
configDeleteFlags(), mScene() {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RemoveVCProcess::~RemoveVCProcess()
{}
RemoveVCProcess::~RemoveVCProcess() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool RemoveVCProcess::IsActive( unsigned int pFlags) const
{
bool RemoveVCProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_RemoveComponent) != 0;
}
// ------------------------------------------------------------------------------------------------
// Small helper function to delete all elements in a T** aray using delete
template <typename T>
inline void ArrayDelete(T**& in, unsigned int& num)
{
inline void ArrayDelete(T **&in, unsigned int &num) {
for (unsigned int i = 0; i < num; ++i)
delete in[i];
delete[] in;
in = NULL;
in = nullptr;
num = 0;
}
@@ -108,9 +102,9 @@ bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
{
childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
// set all children to NULL to make sure they are not deleted when we delete ourself
// set all children to nullptr to make sure they are not deleted when we delete ourself
for (unsigned int i = 0; i < node->mNumChildren;++i)
node->mChildren[i] = NULL;
node->mChildren[i] = nullptr;
}
b = true;
delete node;
@@ -143,86 +137,74 @@ bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveVCProcess::Execute( aiScene* pScene)
{
void RemoveVCProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("RemoveVCProcess begin");
bool bHas = false; //,bMasked = false;
mScene = pScene;
// handle animations
if ( configDeleteFlags & aiComponent_ANIMATIONS)
{
if (configDeleteFlags & aiComponent_ANIMATIONS) {
bHas = true;
ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
ArrayDelete(pScene->mAnimations, pScene->mNumAnimations);
}
// handle textures
if ( configDeleteFlags & aiComponent_TEXTURES)
{
if (configDeleteFlags & aiComponent_TEXTURES) {
bHas = true;
ArrayDelete(pScene->mTextures,pScene->mNumTextures);
ArrayDelete(pScene->mTextures, pScene->mNumTextures);
}
// handle materials
if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
{
if (configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) {
bHas = true;
for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
for (unsigned int i = 1; i < pScene->mNumMaterials; ++i)
delete pScene->mMaterials[i];
pScene->mNumMaterials = 1;
aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
ai_assert(NULL != helper);
aiMaterial *helper = (aiMaterial *)pScene->mMaterials[0];
ai_assert(nullptr != helper);
helper->Clear();
// gray
aiColor3D clr(0.6f,0.6f,0.6f);
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
aiColor3D clr(0.6f, 0.6f, 0.6f);
helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
// add a small ambient color value
clr = aiColor3D(0.05f,0.05f,0.05f);
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
clr = aiColor3D(0.05f, 0.05f, 0.05f);
helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
aiString s;
s.Set("Dummy_MaterialsRemoved");
helper->AddProperty(&s,AI_MATKEY_NAME);
helper->AddProperty(&s, AI_MATKEY_NAME);
}
// handle light sources
if ( configDeleteFlags & aiComponent_LIGHTS)
{
bHas = true;
ArrayDelete(pScene->mLights,pScene->mNumLights);
if (configDeleteFlags & aiComponent_LIGHTS) {
bHas = true;
ArrayDelete(pScene->mLights, pScene->mNumLights);
}
// handle camneras
if ( configDeleteFlags & aiComponent_CAMERAS)
{
if (configDeleteFlags & aiComponent_CAMERAS) {
bHas = true;
ArrayDelete(pScene->mCameras,pScene->mNumCameras);
ArrayDelete(pScene->mCameras, pScene->mNumCameras);
}
// handle meshes
if (configDeleteFlags & aiComponent_MESHES)
{
if (configDeleteFlags & aiComponent_MESHES) {
bHas = true;
ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
}
else
{
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
{
if( ProcessMesh( pScene->mMeshes[a]))
ArrayDelete(pScene->mMeshes, pScene->mNumMeshes);
} else {
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if (ProcessMesh(pScene->mMeshes[a]))
bHas = true;
}
}
// now check whether the result is still a full scene
if (!pScene->mNumMeshes || !pScene->mNumMaterials)
{
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
ASSIMP_LOG_DEBUG("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
@@ -240,63 +222,55 @@ void RemoveVCProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the step
void RemoveVCProcess::SetupProperties(const Importer* pImp)
{
configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
if (!configDeleteFlags)
{
void RemoveVCProcess::SetupProperties(const Importer *pImp) {
configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, 0x0);
if (!configDeleteFlags) {
ASSIMP_LOG_WARN("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
}
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
{
bool RemoveVCProcess::ProcessMesh(aiMesh *pMesh) {
bool ret = false;
// if all materials have been deleted let the material
// index of the mesh point to the created default material
if ( configDeleteFlags & aiComponent_MATERIALS)
if (configDeleteFlags & aiComponent_MATERIALS)
pMesh->mMaterialIndex = 0;
// handle normals
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
{
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) {
delete[] pMesh->mNormals;
pMesh->mNormals = NULL;
pMesh->mNormals = nullptr;
ret = true;
}
// handle tangents and bitangents
if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
{
if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) {
delete[] pMesh->mTangents;
pMesh->mTangents = NULL;
pMesh->mTangents = nullptr;
delete[] pMesh->mBitangents;
pMesh->mBitangents = NULL;
pMesh->mBitangents = nullptr;
ret = true;
}
// handle texture coordinates
bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
{
if (!pMesh->mTextureCoords[i])break;
if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
{
delete [] pMesh->mTextureCoords[i];
pMesh->mTextureCoords[i] = NULL;
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) {
if (!pMesh->mTextureCoords[i]) break;
if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) {
delete[] pMesh->mTextureCoords[i];
pMesh->mTextureCoords[i] = nullptr;
ret = true;
if (!b)
{
if (!b) {
// collapse the rest of the array
for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
pMesh->mTextureCoords[a - 1] = pMesh->mTextureCoords[a];
pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS - 1] = nullptr;
continue;
}
}
@@ -305,22 +279,19 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
// handle vertex colors
b = (0 != (configDeleteFlags & aiComponent_COLORS));
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
{
if (!pMesh->mColors[i])break;
if (configDeleteFlags & aiComponent_COLORSn(i) || b)
{
delete [] pMesh->mColors[i];
pMesh->mColors[i] = NULL;
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) {
if (!pMesh->mColors[i]) break;
if (configDeleteFlags & aiComponent_COLORSn(i) || b) {
delete[] pMesh->mColors[i];
pMesh->mColors[i] = nullptr;
ret = true;
if (!b)
{
if (!b) {
// collapse the rest of the array
for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
pMesh->mColors[a-1] = pMesh->mColors[a];
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a)
pMesh->mColors[a - 1] = pMesh->mColors[a];
pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS - 1] = nullptr;
continue;
}
}
@@ -328,9 +299,8 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
}
// handle bones
if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
{
ArrayDelete(pMesh->mBones,pMesh->mNumBones);
if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) {
ArrayDelete(pMesh->mBones, pMesh->mNumBones);
ret = true;
}
return ret;

View File

@@ -94,4 +94,4 @@ private:
} // Namespace Assimp
#endif // SCALE_PROCESS_H_
#endif // SCALE_PROCESS_H_

View File

@@ -45,111 +45,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* SortByPTypeProcess post-process steps.
*/
// internal headers
#include "ProcessHelper.h"
#include "SortByPTypeProcess.h"
#include "ProcessHelper.h"
#include <assimp/Exceptional.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SortByPTypeProcess::SortByPTypeProcess()
: mConfigRemoveMeshes( 0 ) {
SortByPTypeProcess::SortByPTypeProcess() :
mConfigRemoveMeshes(0) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
SortByPTypeProcess::~SortByPTypeProcess()
{
SortByPTypeProcess::~SortByPTypeProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
{
return (pFlags & aiProcess_SortByPType) != 0;
bool SortByPTypeProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_SortByPType) != 0;
}
// ------------------------------------------------------------------------------------------------
void SortByPTypeProcess::SetupProperties(const Importer* pImp)
{
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
}
// ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
{
if (node->mNumMeshes)
{
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
if (node->mNumMeshes) {
unsigned int newSize = 0;
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
{
unsigned int add = node->mMeshes[m]<<2;
for (unsigned int i = 0; i < 4;++i)
{
if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize;
}
}
if (!newSize)
{
if (!newSize) {
delete[] node->mMeshes;
node->mNumMeshes = 0;
node->mMeshes = NULL;
}
else
{
node->mMeshes = nullptr;
} else {
// Try to reuse the old array if possible
unsigned int* newMeshes = (newSize > node->mNumMeshes
? new unsigned int[newSize] : node->mMeshes);
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
{
unsigned int add = node->mMeshes[m]<<2;
for (unsigned int i = 0; i < 4;++i)
{
if (UINT_MAX != replaceMeshIndex[add+i])
*newMeshes++ = replaceMeshIndex[add+i];
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i])
*newMeshes++ = replaceMeshIndex[add + i];
}
}
if (newSize > node->mNumMeshes)
delete[] node->mMeshes;
node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
}
}
// call all subnodes recursively
for (unsigned int m = 0; m < node->mNumChildren; ++m)
UpdateNodes(replaceMeshIndex,node->mChildren[m]);
UpdateNodes(replaceMeshIndex, node->mChildren[m]);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SortByPTypeProcess::Execute( aiScene* pScene) {
if ( 0 == pScene->mNumMeshes) {
void SortByPTypeProcess::Execute(aiScene *pScene) {
if (0 == pScene->mNumMeshes) {
ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes");
return;
}
ASSIMP_LOG_DEBUG("SortByPTypeProcess begin");
unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
std::vector<aiMesh*> outMeshes;
outMeshes.reserve(pScene->mNumMeshes<<1u);
std::vector<aiMesh *> outMeshes;
outMeshes.reserve(pScene->mNumMeshes << 1u);
bool bAnyChanges = false;
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes * 4, UINT_MAX);
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiMesh* const mesh = pScene->mMeshes[i];
aiMesh *const mesh = pScene->mMeshes[i];
ai_assert(0 != mesh->mPrimitiveTypes);
// if there's just one primitive type in the mesh there's nothing to do for us
@@ -173,11 +158,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
if (1 == num) {
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
*meshIdx = static_cast<unsigned int>( outMeshes.size() );
*meshIdx = static_cast<unsigned int>(outMeshes.size());
outMeshes.push_back(mesh);
} else {
delete mesh;
pScene->mMeshes[ i ] = nullptr;
pScene->mMeshes[i] = nullptr;
bAnyChanges = true;
}
@@ -188,32 +173,29 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
// reuse our current mesh arrays for the submesh
// with the largest number of primitives
unsigned int aiNumPerPType[4] = {0,0,0,0};
aiFace* pFirstFace = mesh->mFaces;
aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
aiFace *pFirstFace = mesh->mFaces;
aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
unsigned int numPolyVerts = 0;
for (;pFirstFace != pLastFace; ++pFirstFace) {
for (; pFirstFace != pLastFace; ++pFirstFace) {
if (pFirstFace->mNumIndices <= 3)
++aiNumPerPType[pFirstFace->mNumIndices-1];
else
{
++aiNumPerPType[pFirstFace->mNumIndices - 1];
else {
++aiNumPerPType[3];
numPolyVerts += pFirstFace-> mNumIndices;
numPolyVerts += pFirstFace->mNumIndices;
}
}
VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
for (unsigned int real = 0; real < 4; ++real,++meshIdx)
{
if ( !aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real))
{
VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
for (unsigned int real = 0; real < 4; ++real, ++meshIdx) {
if (!aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) {
continue;
}
*meshIdx = (unsigned int) outMeshes.size();
*meshIdx = (unsigned int)outMeshes.size();
outMeshes.push_back(new aiMesh());
aiMesh* out = outMeshes.back();
aiMesh *out = outMeshes.back();
// the name carries the adjacency information between the meshes
out->mName = mesh->mName;
@@ -224,13 +206,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
// allocate output storage
out->mNumFaces = aiNumPerPType[real];
aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
aiFace *outFaces = out->mFaces = new aiFace[out->mNumFaces];
out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real + 1));
aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr);
aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
aiVector3D *uv[AI_MAX_NUMBER_OF_TEXTURECOORDS];
aiColor4D *cols[AI_MAX_NUMBER_OF_COLOR_SETS];
if (mesh->mVertices) {
vert = out->mVertices = new aiVector3D[out->mNumVertices];
@@ -241,11 +223,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
}
if (mesh->mTangents) {
tan = out->mTangents = new aiVector3D[out->mNumVertices];
tan = out->mTangents = new aiVector3D[out->mNumVertices];
bit = out->mBitangents = new aiVector3D[out->mNumVertices];
}
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS;++j) {
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++j) {
uv[j] = nullptr;
if (mesh->mTextureCoords[j]) {
uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices];
@@ -254,70 +236,60 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
out->mNumUVComponents[j] = mesh->mNumUVComponents[j];
}
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS;++j) {
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS; ++j) {
cols[j] = nullptr;
if (mesh->mColors[j]) {
cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices];
}
}
typedef std::vector< aiVertexWeight > TempBoneInfo;
std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
typedef std::vector<aiVertexWeight> TempBoneInfo;
std::vector<TempBoneInfo> tempBones(mesh->mNumBones);
// try to guess how much storage we'll need
for (unsigned int q = 0; q < mesh->mNumBones;++q)
{
tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num - 1));
}
unsigned int outIdx = 0;
for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
{
aiFace& in = mesh->mFaces[m];
if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
{
for (unsigned int m = 0; m < mesh->mNumFaces; ++m) {
aiFace &in = mesh->mFaces[m];
if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real + 1)) {
continue;
}
outFaces->mNumIndices = in.mNumIndices;
outFaces->mIndices = in.mIndices;
outFaces->mIndices = in.mIndices;
for (unsigned int q = 0; q < in.mNumIndices; ++q)
{
for (unsigned int q = 0; q < in.mNumIndices; ++q) {
unsigned int idx = in.mIndices[q];
// process all bones of this index
if (avw)
{
VertexWeightTable& tbl = avw[idx];
if (avw) {
VertexWeightTable &tbl = avw[idx];
for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
it != end; ++it)
{
tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
it != end; ++it) {
tempBones[(*it).first].push_back(aiVertexWeight(outIdx, (*it).second));
}
}
if (vert)
{
if (vert) {
*vert++ = mesh->mVertices[idx];
//mesh->mVertices[idx].x = get_qnan();
}
if (nor )*nor++ = mesh->mNormals[idx];
if (tan )
{
*tan++ = mesh->mTangents[idx];
*bit++ = mesh->mBitangents[idx];
if (nor) *nor++ = mesh->mNormals[idx];
if (tan) {
*tan++ = mesh->mTangents[idx];
*bit++ = mesh->mBitangents[idx];
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
{
if (!uv[pp])break;
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) {
if (!uv[pp]) break;
*uv[pp]++ = mesh->mTextureCoords[pp][idx];
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
{
if (!cols[pp])break;
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) {
if (!cols[pp]) break;
*cols[pp]++ = mesh->mColors[pp][idx];
}
@@ -330,23 +302,22 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
ai_assert(outFaces == out->mFaces + out->mNumFaces);
// now generate output bones
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
if (!tempBones[q].empty()) {
++out->mNumBones;
}
}
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
if (!tempBones[q].empty()) {
++out->mNumBones;
}
}
if (out->mNumBones) {
out->mBones = new aiBone*[out->mNumBones];
for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones;++q)
{
TempBoneInfo& in = tempBones[q];
if (in.empty()) {
continue;
}
out->mBones = new aiBone *[out->mNumBones];
for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones; ++q) {
TempBoneInfo &in = tempBones[q];
if (in.empty()) {
continue;
}
aiBone* srcBone = mesh->mBones[q];
aiBone *bone = out->mBones[boneIdx] = new aiBone();
aiBone *srcBone = mesh->mBones[q];
aiBone *bone = out->mBones[boneIdx] = new aiBone();
bone->mName = srcBone->mName;
bone->mOffsetMatrix = srcBone->mOffsetMatrix;
@@ -354,7 +325,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
bone->mNumWeights = (unsigned int)in.size();
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
::memcpy(bone->mWeights, &in[0], bone->mNumWeights * sizeof(aiVertexWeight));
++boneIdx;
}
@@ -371,37 +342,32 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
pScene->mMeshes[i] = nullptr;
}
if (outMeshes.empty())
{
if (outMeshes.empty()) {
// This should not occur
throw DeadlyImportError("No meshes remaining");
}
// If we added at least one mesh process all nodes in the node
// graph and update their respective mesh indices.
if (bAnyChanges)
{
UpdateNodes(replaceMeshIndex,pScene->mRootNode);
if (bAnyChanges) {
UpdateNodes(replaceMeshIndex, pScene->mRootNode);
}
if (outMeshes.size() != pScene->mNumMeshes)
{
if (outMeshes.size() != pScene->mNumMeshes) {
delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)outMeshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
}
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
::memcpy(pScene->mMeshes, &outMeshes[0], pScene->mNumMeshes * sizeof(void *));
if (!DefaultLogger::isNullLogger())
{
if (!DefaultLogger::isNullLogger()) {
char buffer[1024];
::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
::ai_snprintf(buffer, 1024, "Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
ASSIMP_LOG_INFO(buffer);
ASSIMP_LOG_DEBUG("SortByPTypeProcess finished");
}
}

View File

@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <assimp/TinyFormatter.h>
#include <assimp/Exceptional.h>
#include <set>
using namespace Assimp;
using namespace Assimp::Formatter;
@@ -172,7 +173,15 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
const aiBone* bone = pMesh->mBones[a];
for( unsigned int b = 0; b < bone->mNumWeights; ++b)
{
vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
if (bone->mWeights[b].mWeight > 0.0f)
{
int vertexId = bone->mWeights[b].mVertexId;
vertexBones[vertexId].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
if (vertexBones[vertexId].size() > mMaxBoneCount)
{
throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
}
}
}
}
@@ -188,9 +197,6 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
subMeshFaces.reserve( pMesh->mNumFaces);
// accumulated vertex count of all the faces in this submesh
unsigned int numSubMeshVertices = 0;
// a small local array of new bones for the current face. State of all used bones for that face
// can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
std::vector<unsigned int> newBonesAtCurrentFace;
// add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
@@ -200,33 +206,25 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
{
continue;
}
// a small local set of new bones for the current face. State of all used bones for that face
// can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
std::set<unsigned int> newBonesAtCurrentFace;
const aiFace& face = pMesh->mFaces[a];
// check every vertex if its bones would still fit into the current submesh
for( unsigned int b = 0; b < face.mNumIndices; ++b )
{
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
for( unsigned int c = 0; c < vb.size(); ++c)
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
for( unsigned int c = 0; c < vb.size(); ++c)
{
unsigned int boneIndex = vb[c].first;
if( !isBoneUsed[boneIndex] )
{
unsigned int boneIndex = vb[c].first;
// if the bone is already used in this submesh, it's ok
if( isBoneUsed[boneIndex] )
{
continue;
}
// if it's not used, yet, we would need to add it. Store its bone index
if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
{
newBonesAtCurrentFace.push_back( boneIndex);
}
}
newBonesAtCurrentFace.insert(boneIndex);
}
}
}
if (newBonesAtCurrentFace.size() > mMaxBoneCount)
{
throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
}
// leave out the face if the new bones required for this face don't fit the bone count limit anymore
if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
{
@@ -234,17 +232,13 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
}
// mark all new bones as necessary
while( !newBonesAtCurrentFace.empty() )
for (std::set<unsigned int>::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it)
{
unsigned int newIndex = newBonesAtCurrentFace.back();
newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
if( isBoneUsed[newIndex] )
{
continue;
}
isBoneUsed[newIndex] = true;
if (!isBoneUsed[*it])
{
isBoneUsed[*it] = true;
numBones++;
}
}
// store the face index and the vertex count

View File

@@ -508,7 +508,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
aiVector3D* dest, *end;
dest = mesh->mTextureCoords[n];
ai_assert(NULL != src);
ai_assert(nullptr != src);
// Copy the data to the destination array
if (dest != src)

View File

@@ -161,7 +161,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
// Just another check whether aiMesh::mPrimitiveTypes is correct
ai_assert(numOut != pMesh->mNumFaces);
aiVector3D* nor_out = NULL;
aiVector3D *nor_out = nullptr;
// if we don't have normals yet, but expect them to be a cheap side
// product of triangulation anyway, allocate storage for them.
@@ -220,7 +220,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
nface.mNumIndices = face.mNumIndices;
nface.mIndices = face.mIndices;
face.mIndices = NULL;
face.mIndices = nullptr;
continue;
}
// optimized code for quadrilaterals
@@ -272,7 +272,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
sface.mIndices[2] = temp[(start_vertex + 3) % 4];
// prevent double deletion of the indices field
face.mIndices = NULL;
face.mIndices = nullptr;
continue;
}
else
@@ -490,7 +490,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
// drop dumb 0-area triangles - deactivated for now:
//FindDegenerates post processing step can do the same thing
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
// ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
// ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0");
// --curOut;
// delete[] f->mIndices;
@@ -511,7 +511,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
}
delete[] face.mIndices;
face.mIndices = NULL;
face.mIndices = nullptr;
}
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS

File diff suppressed because it is too large Load Diff