Improve STL representation detection

Previously, the STL loader relied on a string check at the start of the
buffer to determine if the STL file was of ASCII representation.  This led to
certain false-positives for binary STL files with the magic string present in
their header.  This patch addresses the issue by adding a proper binary check
to the representation detection.
pull/79/head
Jared Duke 2013-08-16 18:10:19 -07:00
parent 6eaff77a7c
commit 7db5dcb357
1 changed files with 34 additions and 4 deletions

View File

@ -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<const uint32_t*>(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];