Merge pull request #1549 from assimp/issue_104

Issue 104
pull/1551/head^2
Kim Kulling 2017-11-07 13:10:44 +01:00 committed by GitHub
commit a88a23ac7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 176 additions and 61 deletions

View File

@ -80,7 +80,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
return false; 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; const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
return expectedBinaryFileSize == fileSize; return expectedBinaryFileSize == fileSize;
@ -200,17 +202,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 +233,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 +250,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));
@ -269,16 +275,17 @@ void STLImporter::LoadASCIIFile()
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 +307,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 +321,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 +340,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,14 +377,23 @@ 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 +519,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>
// Forward declarations
struct aiNode;
namespace Assimp { 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.
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. * 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:

View File

@ -132,6 +132,7 @@ SET( TEST_SRCS
unit/utX3DImportExport.cpp unit/utX3DImportExport.cpp
unit/utD3MFImportExport.cpp unit/utD3MFImportExport.cpp
unit/utQ3DImportExport.cpp unit/utQ3DImportExport.cpp
unit/utSTLImportExport.cpp
unit/utProfiler.cpp unit/utProfiler.cpp
) )
SET( POST_PROCESSES SET( POST_PROCESSES

View File

@ -0,0 +1,18 @@
solid testTriangle_1
facet normal 0.0 0.0 1.0
outer loop
vertex 1.0 1.0 0.0
vertex -1.0 1.0 0.0
vertex 0.0 -1.0 0.0
endloop
endfacet
endsolid
solid testTriangle_2
facet normal 0.0 0.0 1.0
outer loop
vertex 3.0 3.0 0.0
vertex 2.0 3.0 0.0
vertex 0.0 2.0 0.0
endloop
endfacet
endsolid

View File

@ -0,0 +1,68 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include "SceneDiffer.h"
#include "AbstractImportExportBase.h"
#include <assimp/Importer.hpp>
using namespace Assimp;
class utSTLImporterExporter : public AbstractImportExportBase {
public:
virtual bool importerTest() {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", 0 );
return nullptr != scene;
}
};
TEST_F( utSTLImporterExporter, importXFromFileTest ) {
EXPECT_TRUE( importerTest() );
}
TEST_F( utSTLImporterExporter, test_with_two_solids ) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", 0 );
EXPECT_NE( nullptr, scene );
}