diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 8bfde9656..fff58d04a 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; +namespace { static const aiImporterDesc desc = { "Stereolithography (STL) Importer", "", @@ -64,6 +65,34 @@ static const aiImporterDesc desc = { "stl" }; +// A valid binary STL buffer should consist of the following elements, in order: +// 1) 80 byte header +// 2) 4 byte face count +// 3) 50 bytes per face +bool IsBinarySTL(const char* buffer, unsigned int fileSize) { + if (fileSize < 84) + return false; + + const uint32_t faceCount = *reinterpret_cast(buffer + 80); + const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; + + return expectedBinaryFileSize == fileSize; +} + +// An ascii STL buffer will begin with "solid NAME", where NAME is optional. +// Note: The "solid NAME" check is necessary, but not sufficient, to determine +// if the buffer is ASCII; a binary header could also begin with "solid NAME". +bool IsAsciiSTL(const char* buffer, unsigned int fileSize) { + if (IsBinarySTL(buffer, fileSize)) + return false; + + if (fileSize < 5) + return false; + + return strncmp(buffer, "solid", 5) == 0; +} +} // namespace + // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer STLImporter::STLImporter() @@ -136,12 +165,13 @@ void STLImporter::InternReadFile( const std::string& pFile, bool bMatClr = false; - // check whether the file starts with 'solid' - - // in this case we can simply assume it IS a text file. finished. - if (!::strncmp(mBuffer,"solid",5)) { + if (IsBinarySTL(mBuffer, fileSize)) { + bMatClr = LoadBinaryFile(); + } else if (IsAsciiSTL(mBuffer, fileSize)) { LoadASCIIFile(); + } else { + throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); } - else bMatClr = LoadBinaryFile(); // now copy faces pMesh->mFaces = new aiFace[pMesh->mNumFaces];