closes https://github.com/assimp/assimp/issues/216: check the area of a triangle to check if its degenerated or not.

pull/1558/head
Kim Kulling 2017-11-09 21:31:16 +01:00
parent 9a13bf236f
commit 30e06f7437
4 changed files with 68 additions and 45 deletions

View File

@ -422,7 +422,6 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
return true; return true;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -56,98 +56,131 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
FindDegeneratesProcess::FindDegeneratesProcess() FindDegeneratesProcess::FindDegeneratesProcess()
: configRemoveDegenerates (false) : configRemoveDegenerates (false) {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
FindDegeneratesProcess::~FindDegeneratesProcess() FindDegeneratesProcess::~FindDegeneratesProcess() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const {
{
return 0 != (pFlags & aiProcess_FindDegenerates); return 0 != (pFlags & aiProcess_FindDegenerates);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup import configuration // Setup import configuration
void FindDegeneratesProcess::SetupProperties(const Importer* pImp) void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
{
// Get the current value of AI_CONFIG_PP_FD_REMOVE // Get the current value of AI_CONFIG_PP_FD_REMOVE
configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void FindDegeneratesProcess::Execute( aiScene* pScene) void FindDegeneratesProcess::Execute( aiScene* pScene) {
{
DefaultLogger::get()->debug("FindDegeneratesProcess begin"); DefaultLogger::get()->debug("FindDegeneratesProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
ExecuteOnMesh( pScene->mMeshes[i]); ExecuteOnMesh( pScene->mMeshes[ i ] );
} }
DefaultLogger::get()->debug("FindDegeneratesProcess finished"); DefaultLogger::get()->debug("FindDegeneratesProcess finished");
} }
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
ai_real s = (a + b + c) / 2;
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), 0.5 );
return area;
}
static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) {
const ai_real lx = ( vB.x - vA.x );
const ai_real ly = ( vB.y - vA.y );
const ai_real lz = ( vB.z - vA.z );
ai_real a = lx*lx + ly*ly + lz*lz;
ai_real d = pow( a, 0.5 );
return d;
}
static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
ai_real area = 0;
aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
ai_real a( distance3D( vA, vB ) );
ai_real b( distance3D( vB, vC ) );
ai_real c( distance3D( vC, vA ) );
area = heron( a, b, c );
return area;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh // Executes the post processing step on the given imported mesh
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
{
mesh->mPrimitiveTypes = 0; mesh->mPrimitiveTypes = 0;
std::vector<bool> remove_me; std::vector<bool> remove_me;
if (configRemoveDegenerates) if (configRemoveDegenerates) {
remove_me.resize(mesh->mNumFaces,false); remove_me.resize( mesh->mNumFaces, false );
}
unsigned int deg = 0, limit; unsigned int deg = 0, limit;
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) {
{
aiFace& face = mesh->mFaces[a]; aiFace& face = mesh->mFaces[a];
bool first = true; bool first = true;
// check whether the face contains degenerated entries // check whether the face contains degenerated entries
for (unsigned int i = 0; i < face.mNumIndices; ++i) for (unsigned int i = 0; i < face.mNumIndices; ++i) {
{
// Polygons with more than 4 points are allowed to have double points, that is // Polygons with more than 4 points are allowed to have double points, that is
// simulating polygons with holes just with concave polygons. However, // simulating polygons with holes just with concave polygons. However,
// double points may not come directly after another. // double points may not come directly after another.
limit = face.mNumIndices; limit = face.mNumIndices;
if (face.mNumIndices > 4) if (face.mNumIndices > 4) {
limit = std::min(limit,i+2); limit = std::min( limit, i+2 );
}
for (unsigned int t = i+1; t < limit; ++t) for (unsigned int t = i+1; t < limit; ++t) {
{ if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) {
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
{
// we have found a matching vertex position // we have found a matching vertex position
// remove the corresponding index from the array // remove the corresponding index from the array
--face.mNumIndices;--limit; --face.mNumIndices;
for (unsigned int m = t; m < face.mNumIndices; ++m) --limit;
{ for (unsigned int m = t; m < face.mNumIndices; ++m) {
face.mIndices[m] = face.mIndices[m+1]; face.mIndices[ m ] = face.mIndices[ m+1 ];
} }
--t; --t;
// NOTE: we set the removed vertex index to an unique value // NOTE: we set the removed vertex index to an unique value
// to make sure the developer gets notified when his // to make sure the developer gets notified when his
// application attemps to access this data. // application attemps to access this data.
face.mIndices[face.mNumIndices] = 0xdeadbeef; face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
if(first) if(first) {
{
++deg; ++deg;
first = false; first = false;
} }
if (configRemoveDegenerates) { if ( configRemoveDegenerates ) {
remove_me[a] = true; remove_me[ a ] = true;
goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
} }
} }
} }
ai_real area = calculateAreaOfTriangle( face, mesh );
if ( area < 1e-6 ) {
if ( configRemoveDegenerates ) {
remove_me[ a ] = true;
goto evil_jump_outside;
}
// todo: check for index which is corrupt.
}
} }
// We need to update the primitive flags array of the mesh. // We need to update the primitive flags array of the mesh.

View File

@ -207,12 +207,6 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
} }
// add all created meshes to the single node
/*pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
pScene->mRootNode->mMeshes[i] = i;
*/
// create a single default material, using a white diffuse color for consistency with // create a single default material, using a white diffuse color for consistency with
// other geometric types (e.g., PLY). // other geometric types (e.g., PLY).
aiMaterial* pcMat = new aiMaterial(); aiMaterial* pcMat = new aiMaterial();

View File

@ -65,14 +65,11 @@ struct Node;
/** The XFileImporter is a worker class capable of importing a scene from a /** The XFileImporter is a worker class capable of importing a scene from a
* DirectX file .x * DirectX file .x
*/ */
class XFileImporter : public BaseImporter class XFileImporter : public BaseImporter {
{
public: public:
XFileImporter(); XFileImporter();
~XFileImporter(); ~XFileImporter();
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */