closes https://github.com/assimp/assimp/issues/216: check the area of a triangle to check if its degenerated or not.
parent
9a13bf236f
commit
30e06f7437
|
@ -422,7 +422,6 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Reference in New Issue