closes https://github.com/assimp/assimp/issues/104: deal with more solids in one STL file.

pull/1549/head
Kim Kulling 2017-11-06 22:30:07 +01:00
parent 02b042d78e
commit 9a9f18bbed
2 changed files with 86 additions and 60 deletions

View File

@ -200,17 +200,17 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
if (IsBinarySTL(mBuffer, fileSize)) { if (IsBinarySTL(mBuffer, fileSize)) {
bMatClr = LoadBinaryFile(); bMatClr = LoadBinaryFile();
} else if (IsAsciiSTL(mBuffer, fileSize)) { } else if (IsAsciiSTL(mBuffer, fileSize)) {
LoadASCIIFile(); LoadASCIIFile( pScene->mRootNode );
} else { } else {
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 // add all created meshes to the single node
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; /*pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes; i++) for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
pScene->mRootNode->mMeshes[i] = 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();
@ -231,11 +231,12 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials = new aiMaterial*[1];
pScene->mMaterials[0] = pcMat; pScene->mMaterials[0] = pcMat;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read an ASCII STL file // Read an ASCII STL file
void STLImporter::LoadASCIIFile() void STLImporter::LoadASCIIFile( aiNode *root ) {
{
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiNode*> nodes;
const char* sz = mBuffer; const char* sz = mBuffer;
const char* bufferEnd = mBuffer + fileSize; const char* bufferEnd = mBuffer + fileSize;
std::vector<aiVector3D> positionBuffer; std::vector<aiVector3D> positionBuffer;
@ -247,12 +248,15 @@ void STLImporter::LoadASCIIFile()
positionBuffer.reserve(sizeEstimate); positionBuffer.reserve(sizeEstimate);
normalBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate);
while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) {
{ std::vector<unsigned int> meshIndices;
aiMesh* pMesh = new aiMesh(); aiMesh* pMesh = new aiMesh();
pMesh->mMaterialIndex = 0; pMesh->mMaterialIndex = 0;
meshIndices.push_back( meshes.size() );
meshes.push_back(pMesh); meshes.push_back(pMesh);
aiNode *node = new aiNode;
node->mParent = root;
nodes.push_back( node );
SkipSpaces(&sz); SkipSpaces(&sz);
ai_assert(!IsLineEnd(sz)); ai_assert(!IsLineEnd(sz));
@ -265,20 +269,21 @@ void STLImporter::LoadASCIIFile()
size_t temp; size_t temp;
// setup the name of the node // setup the name of the node
if ((temp = (size_t)(sz-szMe))) { if ((temp = (size_t)(sz-szMe))) {
if (temp >= MAXLEN) { if (temp >= MAXLEN) {
throw DeadlyImportError( "STL: Node name too long" ); throw DeadlyImportError( "STL: Node name too long" );
} }
std::string name( szMe, temp );
pScene->mRootNode->mName.length = temp; node->mName.Set( name.c_str() );
memcpy(pScene->mRootNode->mName.data,szMe,temp); //pScene->mRootNode->mName.length = temp;
pScene->mRootNode->mName.data[temp] = '\0'; //memcpy(pScene->mRootNode->mName.data,szMe,temp);
//pScene->mRootNode->mName.data[temp] = '\0';
} else {
pScene->mRootNode->mName.Set("<STL_ASCII>");
} }
else pScene->mRootNode->mName.Set("<STL_ASCII>");
unsigned int faceVertexCounter = 3; unsigned int faceVertexCounter = 3;
for ( ;; ) for ( ;; ) {
{
// go to the next token // go to the next token
if(!SkipSpacesAndLineEnd(&sz)) if(!SkipSpacesAndLineEnd(&sz))
{ {
@ -300,9 +305,7 @@ void STLImporter::LoadASCIIFile()
SkipSpaces(&sz); SkipSpaces(&sz);
if (strncmp(sz,"normal",6)) { if (strncmp(sz,"normal",6)) {
DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
} } else {
else
{
if (sz[6] == '\0') { if (sz[6] == '\0') {
throw DeadlyImportError("STL: unexpected EOF while parsing facet"); throw DeadlyImportError("STL: unexpected EOF while parsing facet");
} }
@ -316,16 +319,11 @@ void STLImporter::LoadASCIIFile()
normalBuffer.push_back(*vn); normalBuffer.push_back(*vn);
normalBuffer.push_back(*vn); normalBuffer.push_back(*vn);
} }
} } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000
// vertex 1.50000 1.50000 0.00000
else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
{
if (faceVertexCounter >= 3) { if (faceVertexCounter >= 3) {
DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
++sz; ++sz;
} } else {
else
{
if (sz[6] == '\0') { if (sz[6] == '\0') {
throw DeadlyImportError("STL: unexpected EOF while parsing facet"); throw DeadlyImportError("STL: unexpected EOF while parsing facet");
} }
@ -340,17 +338,14 @@ void STLImporter::LoadASCIIFile()
sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z ); sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z );
faceVertexCounter++; faceVertexCounter++;
} }
} } else if (!::strncmp(sz,"endsolid",8)) {
else if (!::strncmp(sz,"endsolid",8)) {
do { do {
++sz; ++sz;
} while (!::IsLineEnd(*sz)); } while (!::IsLineEnd(*sz));
SkipSpacesAndLineEnd(&sz); SkipSpacesAndLineEnd(&sz);
// finished! // finished!
break; break;
} } else { // else skip the whole identifier
// else skip the whole identifier
else {
do { do {
++sz; ++sz;
} while (!::IsSpaceOrNewLine(*sz)); } while (!::IsSpaceOrNewLine(*sz));
@ -380,13 +375,22 @@ void STLImporter::LoadASCIIFile()
// now copy faces // now copy faces
addFacesToMesh(pMesh); addFacesToMesh(pMesh);
// assign the meshes to the current node
pushMeshesToNode( meshIndices, node );
} }
// now add the loaded meshes // now add the loaded meshes
pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mNumMeshes = (unsigned int)meshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
for (size_t i = 0; i < meshes.size(); i++) for (size_t i = 0; i < meshes.size(); i++) {
{ pScene->mMeshes[ i ] = meshes[i];
pScene->mMeshes[i] = meshes[i]; }
root->mNumChildren = nodes.size();
root->mChildren = new aiNode*[ root->mNumChildren ];
for ( size_t i=0; i<nodes.size(); ++i ) {
root->mChildren[ i ] = nodes[ i ];
} }
} }
@ -513,4 +517,18 @@ bool STLImporter::LoadBinaryFile()
return false; return false;
} }
void STLImporter::pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node ) {
ai_assert( nullptr != node );
if ( meshIndices.empty() ) {
return;
}
node->mNumMeshes = static_cast<unsigned int>( meshIndices.size() );
node->mMeshes = new unsigned int[ meshIndices.size() ];
for ( size_t i=0; i<meshIndices.size(); ++i ) {
node->mMeshes[ i ] = meshIndices[ i ];
}
meshIndices.clear();
}
#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER

View File

@ -48,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include <assimp/types.h> #include <assimp/types.h>
namespace Assimp { // Forward declarations
class aiNode;
namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Importer class for the sterolithography STL file format /**
*/ * @brief Importer class for the sterolithography STL file format.
class STLImporter : public BaseImporter */
{ class STLImporter : public BaseImporter {
public: public:
/**
* @brief STLImporter, the class default constructor.
*/
STLImporter(); STLImporter();
/**
* @brief The class destructor.
*/
~STLImporter(); ~STLImporter();
/**
public: * @brief Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
*/ */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- /**
/** Return importer meta information. * @brief Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- /**
/** Imports the given file into the given scene structure. * @brief Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
/**
// ------------------------------------------------------------------- * @brief Loads a binary .stl file
/** Loads a binary .stl file
* @return true if the default vertex color must be used as material color * @return true if the default vertex color must be used as material color
*/ */
bool LoadBinaryFile(); bool LoadBinaryFile();
// ------------------------------------------------------------------- /**
/** Loads a ASCII text .stl file * @brief Loads a ASCII text .stl file
*/ */
void LoadASCIIFile(); void LoadASCIIFile( aiNode *root );
void pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node );
protected: protected: