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
parent
6eaff77a7c
commit
7db5dcb357
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue