diff options
Diffstat (limited to 'src/3rdparty/assimp/code/STLLoader.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/STLLoader.cpp | 158 |
1 files changed, 91 insertions, 67 deletions
diff --git a/src/3rdparty/assimp/code/STLLoader.cpp b/src/3rdparty/assimp/code/STLLoader.cpp index 95fce47e2..be4c7584d 100644 --- a/src/3rdparty/assimp/code/STLLoader.cpp +++ b/src/3rdparty/assimp/code/STLLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,10 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/IOSystem.hpp> #include <assimp/scene.h> #include <assimp/DefaultLogger.hpp> +#include <assimp/importerdesc.h> using namespace Assimp; namespace { + static const aiImporterDesc desc = { "Stereolithography (STL) Importer", "", @@ -78,7 +81,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) { return false; } - const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80); + const char *facecount_pos = buffer + 80; + uint32_t faceCount( 0 ); + ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) ); const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; return expectedBinaryFileSize == fileSize; @@ -144,7 +149,7 @@ bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool const char* tokens[] = {"STL","solid"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); } - + return false; } @@ -168,8 +173,7 @@ void addFacesToMesh(aiMesh* pMesh) // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void STLImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) +void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); @@ -189,7 +193,7 @@ void STLImporter::InternReadFile( const std::string& pFile, this->mBuffer = &mBuffer2[0]; // the default vertex color is light gray. - clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f; + clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = (ai_real) 0.6; // allocate a single node pScene->mRootNode = new aiNode(); @@ -199,42 +203,37 @@ void STLImporter::InternReadFile( const std::string& pFile, if (IsBinarySTL(mBuffer, fileSize)) { bMatClr = LoadBinaryFile(); } else if (IsAsciiSTL(mBuffer, fileSize)) { - LoadASCIIFile(); + LoadASCIIFile( pScene->mRootNode ); } else { 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 light gray diffuse color for consistency with + // create a single default material, using a white diffuse color for consistency with // other geometric types (e.g., PLY). aiMaterial* pcMat = new aiMaterial(); aiString s; s.Set(AI_DEFAULT_MATERIAL_NAME); pcMat->AddProperty(&s, AI_MATKEY_NAME); - aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f); + aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0)); if (bMatClr) { clrDiffuse = clrColorDefault; } pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE); pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR); - clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f); + clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0)); pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT); pScene->mNumMaterials = 1; pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials[0] = pcMat; } + // ------------------------------------------------------------------------------------------------ // Read an ASCII STL file -void STLImporter::LoadASCIIFile() -{ +void STLImporter::LoadASCIIFile( aiNode *root ) { std::vector<aiMesh*> meshes; + std::vector<aiNode*> nodes; const char* sz = mBuffer; const char* bufferEnd = mBuffer + fileSize; std::vector<aiVector3D> positionBuffer; @@ -246,12 +245,15 @@ void STLImporter::LoadASCIIFile() positionBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate); - while (IsAsciiSTL(sz, bufferEnd - sz)) - { + while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) { + std::vector<unsigned int> meshIndices; aiMesh* pMesh = new aiMesh(); pMesh->mMaterialIndex = 0; + meshIndices.push_back((unsigned int) meshes.size() ); meshes.push_back(pMesh); - + aiNode *node = new aiNode; + node->mParent = root; + nodes.push_back( node ); SkipSpaces(&sz); ai_assert(!IsLineEnd(sz)); @@ -264,20 +266,21 @@ void STLImporter::LoadASCIIFile() size_t temp; // setup the name of the node - if ((temp = (size_t)(sz-szMe))) { + if ((temp = (size_t)(sz-szMe))) { if (temp >= MAXLEN) { throw DeadlyImportError( "STL: Node name too long" ); } - - pScene->mRootNode->mName.length = temp; - memcpy(pScene->mRootNode->mName.data,szMe,temp); - pScene->mRootNode->mName.data[temp] = '\0'; + std::string name( szMe, temp ); + node->mName.Set( name.c_str() ); + //pScene->mRootNode->mName.length = temp; + //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 = 0; - for ( ;; ) - { + unsigned int faceVertexCounter = 3; + for ( ;; ) { // go to the next token if(!SkipSpacesAndLineEnd(&sz)) { @@ -299,32 +302,25 @@ void STLImporter::LoadASCIIFile() SkipSpaces(&sz); if (strncmp(sz,"normal",6)) { DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } sz += 7; SkipSpaces(&sz); - sz = fast_atoreal_move<float>(sz, (float&)vn->x ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->x ); SkipSpaces(&sz); - sz = fast_atoreal_move<float>(sz, (float&)vn->y ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->y ); SkipSpaces(&sz); - sz = fast_atoreal_move<float>(sz, (float&)vn->z ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z ); normalBuffer.push_back(*vn); normalBuffer.push_back(*vn); } - } - // vertex 1.50000 1.50000 0.00000 - else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) - { + } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); ++sz; - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } @@ -332,24 +328,21 @@ void STLImporter::LoadASCIIFile() SkipSpaces(&sz); positionBuffer.push_back(aiVector3D()); aiVector3D* vn = &positionBuffer.back(); - sz = fast_atoreal_move<float>(sz, (float&)vn->x ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->x ); SkipSpaces(&sz); - sz = fast_atoreal_move<float>(sz, (float&)vn->y ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->y ); SkipSpaces(&sz); - sz = fast_atoreal_move<float>(sz, (float&)vn->z ); + sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z ); faceVertexCounter++; } - } - else if (!::strncmp(sz,"endsolid",8)) { + } else if (!::strncmp(sz,"endsolid",8)) { do { ++sz; } while (!::IsLineEnd(*sz)); SkipSpacesAndLineEnd(&sz); // finished! break; - } - // else skip the whole identifier - else { + } else { // else skip the whole identifier do { ++sz; } while (!::IsSpaceOrNewLine(*sz)); @@ -368,8 +361,8 @@ void STLImporter::LoadASCIIFile() pMesh->mNumFaces = 0; throw DeadlyImportError("Normal buffer size does not match position buffer size"); } - pMesh->mNumFaces = positionBuffer.size() / 3; - pMesh->mNumVertices = positionBuffer.size(); + pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3); + pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size()); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); positionBuffer.clear(); @@ -379,13 +372,22 @@ void STLImporter::LoadASCIIFile() // now copy faces addFacesToMesh(pMesh); + + // assign the meshes to the current node + pushMeshesToNode( meshIndices, node ); } + // now add the loaded meshes pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (size_t i = 0; i < meshes.size(); i++) - { - pScene->mMeshes[i] = meshes[i]; + for (size_t i = 0; i < meshes.size(); i++) { + pScene->mMeshes[ i ] = meshes[i]; + } + + root->mNumChildren = (unsigned int) nodes.size(); + root->mChildren = new aiNode*[ root->mNumChildren ]; + for ( size_t i=0; i<nodes.size(); ++i ) { + root->mChildren[ i ] = nodes[ i ]; } } @@ -416,10 +418,11 @@ bool STLImporter::LoadBinaryFile() // read the default vertex color for facets bIsMaterialise = true; DefaultLogger::get()->info("STL: Taking code path for Materialise files"); - clrColorDefault.r = (*sz2++) / 255.0f; - clrColorDefault.g = (*sz2++) / 255.0f; - clrColorDefault.b = (*sz2++) / 255.0f; - clrColorDefault.a = (*sz2++) / 255.0f; + const ai_real invByte = (ai_real)1.0 / ( ai_real )255.0; + clrColorDefault.r = (*sz2++) * invByte; + clrColorDefault.g = (*sz2++) * invByte; + clrColorDefault.b = (*sz2++) * invByte; + clrColorDefault.a = (*sz2++) * invByte; break; } } @@ -480,18 +483,19 @@ bool STLImporter::LoadBinaryFile() DefaultLogger::get()->info("STL: Mesh has vertex colors"); } aiColor4D* clr = &pMesh->mColors[0][i*3]; - clr->a = 1.0f; + clr->a = 1.0; + const ai_real invVal( (ai_real)1.0 / ( ai_real )31.0 ); if (bIsMaterialise) // this is reversed { - clr->r = (color & 0x31u) / 31.0f; - clr->g = ((color & (0x31u<<5))>>5u) / 31.0f; - clr->b = ((color & (0x31u<<10))>>10u) / 31.0f; + clr->r = (color & 0x31u) *invVal; + clr->g = ((color & (0x31u<<5))>>5u) *invVal; + clr->b = ((color & (0x31u<<10))>>10u) *invVal; } else { - clr->b = (color & 0x31u) / 31.0f; - clr->g = ((color & (0x31u<<5))>>5u) / 31.0f; - clr->r = ((color & (0x31u<<10))>>10u) / 31.0f; + clr->b = (color & 0x31u) *invVal; + clr->g = ((color & (0x31u<<5))>>5u) *invVal; + clr->r = ((color & (0x31u<<10))>>10u) *invVal; } // assign the color to all vertices of the face *(clr+1) = *clr; @@ -502,6 +506,12 @@ bool STLImporter::LoadBinaryFile() // now copy faces addFacesToMesh(pMesh); + // 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; + if (bIsMaterialise && !pMesh->mColors[0]) { // use the color as diffuse material color @@ -510,4 +520,18 @@ bool STLImporter::LoadBinaryFile() 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 |