Prechádzať zdrojové kódy

Merge branch 'master' into assbin_test

Kim Kulling 7 rokov pred
rodič
commit
c1ed5e0048

+ 0 - 2
code/Assimp.cpp

@@ -272,8 +272,6 @@ void aiReleaseImport( const aiScene* pScene)
 
     ASSIMP_BEGIN_EXCEPTION_REGION();
 
-    aiReleaseDefaultMaterial();
-
     // find the importer associated with this data
     const ScenePrivateData* priv = ScenePriv(pScene);
     if( !priv || !priv->mOrigImporter)  {

+ 8 - 5
code/D3MFImporter.cpp

@@ -297,8 +297,9 @@ private:
             return false;
         }
 
+        //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
         const size_t len( strlen( color ) );
-        if ( 9 != len ) {
+        if ( 9 != len && 7 != len) {
             return false;
         }
 
@@ -313,26 +314,28 @@ private:
         ++buf;
         comp[ 1 ] = *buf;
         ++buf;
-        diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) );
+        diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) ) / 255.0;
 
 
         comp[ 0 ] = *buf;
         ++buf;
         comp[ 1 ] = *buf;
         ++buf;
-        diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+        diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
 
         comp[ 0 ] = *buf;
         ++buf;
         comp[ 1 ] = *buf;
         ++buf;
-        diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+        diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
 
+        if(7 == len)
+            return true;
         comp[ 0 ] = *buf;
         ++buf;
         comp[ 1 ] = *buf;
         ++buf;
-        diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+        diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
 
         return true;
     }

+ 0 - 2
code/Importer.cpp

@@ -178,7 +178,6 @@ Importer::~Importer()
 {
     // Delete all import plugins
 	DeleteImporterInstanceList(pimpl->mImporter);
-    aiReleaseDefaultMaterial();
 
     // Delete all post-processing plug-ins
     for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
@@ -385,7 +384,6 @@ void Importer::FreeScene( )
 {
     ASSIMP_BEGIN_EXCEPTION_REGION();
 
-    aiReleaseDefaultMaterial();
     delete pimpl->mScene;
     pimpl->mScene = NULL;
 

+ 0 - 20
code/MaterialSystem.cpp

@@ -387,26 +387,6 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
     return AI_SUCCESS;
 }
 
-static aiMaterial *DefaultMaterial = nullptr;
-
-// ------------------------------------------------------------------------------------------------
-// Will return the default material.
-aiMaterial *aiCreateAndRegisterDefaultMaterial() {
-    if (nullptr == DefaultMaterial) {
-        DefaultMaterial = new aiMaterial;
-        aiString s;
-        s.Set(AI_DEFAULT_MATERIAL_NAME);
-        DefaultMaterial->AddProperty(&s, AI_MATKEY_NAME);
-    }
-
-    return DefaultMaterial;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Will return the default material.
-void aiReleaseDefaultMaterial() {
-    DefaultMaterial = nullptr;
-}
 
 static const unsigned int DefaultNumAllocated = 5;
 

+ 21 - 22
code/ObjFileImporter.cpp

@@ -211,12 +211,29 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
     }
 
     if (pModel->m_Objects.size() > 0) {
+
+        unsigned int meshCount = 0;
+        unsigned int childCount = 0;
+
+        for(size_t index = 0; index < pModel->m_Objects.size(); ++index) {
+            if(pModel->m_Objects[index]) {
+                ++childCount;
+                meshCount += (unsigned int)pModel->m_Objects[index]->m_Meshes.size();
+            }
+        }
+
+        // Allocate space for the child nodes on the root node
+        pScene->mRootNode->mChildren = new aiNode*[ childCount ];
+
         // Create nodes for the whole scene
         std::vector<aiMesh*> MeshArray;
+        MeshArray.reserve(meshCount);
         for (size_t index = 0; index < pModel->m_Objects.size(); ++index) {
             createNodes(pModel, pModel->m_Objects[index], pScene->mRootNode, pScene, MeshArray);
         }
 
+        ai_assert(pScene->mRootNode->mNumChildren == childCount);
+
         // Create mesh pointer buffer for this scene
         if (pScene->mNumMeshes > 0) {
             pScene->mMeshes = new aiMesh*[MeshArray.size()];
@@ -287,9 +304,8 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
     pNode->mName = pObject->m_strObjName;
 
     // If we have a parent node, store it
-    if( pParent != NULL ) {
-        appendChildToParentNode( pParent, pNode );
-    }
+    ai_assert( NULL != pParent );
+    appendChildToParentNode( pParent, pNode );
 
     for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) {
         unsigned int meshId = pObject->m_Meshes[ i ];
@@ -442,8 +458,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
     pMesh->mNumVertices = numIndices;
     if (pMesh->mNumVertices == 0) {
         throw DeadlyImportError( "OBJ: no vertices" );
-    } else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
-        throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" );
+    } else if (pMesh->mNumVertices > AI_MAX_VERTICES) {
+        throw DeadlyImportError( "OBJ: Too many vertices" );
     }
     pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
 
@@ -770,25 +786,8 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
     // Assign parent to child
     pChild->mParent = pParent;
 
-    // If already children was assigned to the parent node, store them in a
-    std::vector<aiNode*> temp;
-    if (pParent->mChildren != NULL)
-    {
-        ai_assert( 0 != pParent->mNumChildren );
-        for (size_t index = 0; index < pParent->mNumChildren; index++)
-        {
-            temp.push_back(pParent->mChildren [ index ] );
-        }
-        delete [] pParent->mChildren;
-    }
-
     // Copy node instances into parent node
     pParent->mNumChildren++;
-    pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
-    for (size_t index = 0; index < pParent->mNumChildren-1; index++)
-    {
-        pParent->mChildren[ index ] = temp [ index ];
-    }
     pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
 }
 

+ 2 - 3
code/STLLoader.cpp

@@ -214,11 +214,10 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
 
     // create a single default material, using a white diffuse color for consistency with
     // other geometric types (e.g., PLY).
-    aiMaterial* pcMat = aiCreateAndRegisterDefaultMaterial();
-    /*aiMaterial* pcMat = new aiMaterial();
+    aiMaterial* pcMat = new aiMaterial();
     aiString s;
     s.Set(AI_DEFAULT_MATERIAL_NAME);
-    pcMat->AddProperty(&s, AI_MATKEY_NAME);*/
+    pcMat->AddProperty(&s, AI_MATKEY_NAME);
 
     aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0));
     if (bMatClr) {

+ 0 - 20
include/assimp/material.h

@@ -1565,26 +1565,6 @@ C_ENUM aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
     unsigned int* flags                 /*= NULL*/);
 #endif // !#ifdef __cplusplus
 
-// ---------------------------------------------------------------------------
-/** @brief  Helper function to get all values pertaining to a particular
-*  texture slot from a material structure.
-*
-*  @return Pointer showing to the default material.
-*/
-// ---------------------------------------------------------------------------
-#ifdef __cplusplus
-ASSIMP_API aiMaterial *aiCreateAndRegisterDefaultMaterial(void);
-#else
-C_STRUCT aiMaterial *aiCreateAndRegisterDefaultMaterial(void);
-#endif // !#ifdef __cplusplus
-
-// ---------------------------------------------------------------------------
-/**
-  * @brief  Helper function to release the default material instance, the
-  *         instance will not be destroyed.
-  */
-// ---------------------------------------------------------------------------
-ASSIMP_API void aiReleaseDefaultMaterial();
 
 #ifdef __cplusplus
 }

+ 53 - 18
port/PyAssimp/pyassimp/core.py

@@ -66,6 +66,13 @@ def make_tuple(ai_obj, type = None):
 
     return res
 
+# Returns unicode object for Python 2, and str object for Python 3.
+def _convert_assimp_string(assimp_string):
+    try:
+        return unicode(assimp_string.data, errors='ignore')
+    except:
+        return str(assimp_string.data, errors='ignore')
+
 # It is faster and more correct to have an init function for each assimp class
 def _init_face(aiFace):
     aiFace.indices = [aiFace.mIndices[i] for i in range(aiFace.mNumIndices)]
@@ -118,14 +125,9 @@ def _init(self, target = None, parent = None):
                 continue
 
         if m == 'mName':
-            obj = self.mName
-            try:
-                uni = unicode(obj.data, errors='ignore')
-            except:
-                uni = str(obj.data, errors='ignore')
-            target.name = str( uni )
-            target.__class__.__repr__ = lambda x: str(x.__class__) + "(" + getattr(x, 'name','') + ")"
-            target.__class__.__str__ = lambda x: getattr(x, 'name', '')
+            target.name = str(_convert_assimp_string(self.mName))
+            target.__class__.__repr__ = lambda x: str(x.__class__) + "(" + getattr(x, 'name','') + ")"
+            target.__class__.__str__ = lambda x: getattr(x, 'name', '')
             continue
 
         name = m[1:].lower()
@@ -220,6 +222,9 @@ def _init(self, target = None, parent = None):
     if isinstance(self, structs.Texture):
         _finalize_texture(self, target)
 
+    if isinstance(self, structs.Metadata):
+        _finalize_metadata(self, target)
+
 
     return self
 
@@ -412,6 +417,43 @@ def _finalize_mesh(mesh, target):
         faces = [f.indices for f in target.faces]
     setattr(target, 'faces', faces)
 
+def _init_metadata_entry(entry):
+    from ctypes import POINTER, c_bool, c_int32, c_uint64, c_float, c_double, cast
+
+    entry.type = entry.mType
+    if entry.type == structs.MetadataEntry.AI_BOOL:
+        entry.data = cast(entry.mData, POINTER(c_bool)).contents.value
+    elif entry.type == structs.MetadataEntry.AI_INT32:
+        entry.data = cast(entry.mData, POINTER(c_int32)).contents.value
+    elif entry.type == structs.MetadataEntry.AI_UINT64:
+        entry.data = cast(entry.mData, POINTER(c_uint64)).contents.value
+    elif entry.type == structs.MetadataEntry.AI_FLOAT:
+        entry.data = cast(entry.mData, POINTER(c_float)).contents.value
+    elif entry.type == structs.MetadataEntry.AI_DOUBLE:
+        entry.data = cast(entry.mData, POINTER(c_double)).contents.value
+    elif entry.type == structs.MetadataEntry.AI_AISTRING:
+        assimp_string = cast(entry.mData, POINTER(structs.String)).contents
+        entry.data = _convert_assimp_string(assimp_string)
+    elif entry.type == structs.MetadataEntry.AI_AIVECTOR3D:
+        assimp_vector = cast(entry.mData, POINTER(structs.Vector3D)).contents
+        entry.data = make_tuple(assimp_vector)
+
+    return entry
+
+def _finalize_metadata(metadata, target):
+    """ Building the metadata object is a bit specific.
+
+    Firstly, there are two separate arrays: one with metadata keys and one
+    with metadata values, and there are no corresponding mNum* attributes,
+    so the C arrays are not converted to Python arrays using the generic
+    code in the _init function.
+
+    Secondly, a metadata entry value has to be cast according to declared
+    metadata entry type.
+    """
+    length = metadata.mNumProperties
+    setattr(target, 'keys', [str(_convert_assimp_string(metadata.mKeys[i])) for i in range(length)])
+    setattr(target, 'values', [_init_metadata_entry(metadata.mValues[i]) for i in range(length)])
 
 class PropertyGetter(dict):
     def __getitem__(self, key):
@@ -443,11 +485,8 @@ def _get_properties(properties, length):
     for p in [properties[i] for i in range(length)]:
         #the name
         p = p.contents
-        try:
-            uni = unicode(p.mKey.data, errors='ignore')
-        except:
-            uni = str(p.mKey.data, errors='ignore')
-        key = (str(uni).split('.')[1], p.mSemantic)
+        key = str(_convert_assimp_string(p.mKey))
+        key = (key.split('.')[1], p.mSemantic)
 
         #the data
         from ctypes import POINTER, cast, c_int, c_float, sizeof
@@ -455,11 +494,7 @@ def _get_properties(properties, length):
             arr = cast(p.mData, POINTER(c_float * int(p.mDataLength/sizeof(c_float)) )).contents
             value = [x for x in arr]
         elif p.mType == 3: #string can't be an array
-            try:
-                uni = unicode(cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data, errors='ignore')
-            except:
-                uni = str(cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data, errors='ignore')
-            value = uni
+            value = _convert_assimp_string(cast(p.mData, POINTER(structs.MaterialPropertyString)).contents)
 
         elif p.mType == 4:
             arr = cast(p.mData, POINTER(c_int * int(p.mDataLength/sizeof(c_int)) )).contents

+ 2 - 2
port/PyAssimp/pyassimp/structs.py

@@ -291,7 +291,7 @@ Node._fields_ = [
 
             # Metadata associated with this node or NULL if there is no metadata.
             # Whether any metadata is generated depends on the source file format.
-            ("mMetadata", POINTER(POINTER(Metadata))),
+            ("mMetadata", POINTER(Metadata)),
         ]
 
 class Light(Structure):
@@ -939,7 +939,7 @@ class Scene(Structure):
             # This data contains global metadata which belongs to the scene like
             # unit-conversions, versions, vendors or other model-specific data. This
             # can be used to store format-specific metadata as well.
-            ("mMetadata", POINTER(POINTER(Metadata))),
+            ("mMetadata", POINTER(Metadata)),
         ]
 
 assimp_structs_as_tuple = (Matrix4x4,

+ 1 - 9
test/unit/utMaterialSystem.cpp

@@ -129,18 +129,10 @@ TEST_F(MaterialSystemTest, testStringProperty) {
     EXPECT_STREQ("Hello, this is a small test", s.data);
 }
 
-// ------------------------------------------------------------------------------------------------
-TEST_F(MaterialSystemTest, testDefaultMaterialAccess) {
-    aiMaterial *mat = aiCreateAndRegisterDefaultMaterial();
-    EXPECT_NE(nullptr, mat);
-    aiReleaseDefaultMaterial();
-
-    delete mat;
-}
 
 // ------------------------------------------------------------------------------------------------
 TEST_F(MaterialSystemTest, testMaterialNameAccess) {
-    aiMaterial *mat = aiCreateAndRegisterDefaultMaterial();
+    aiMaterial *mat = new aiMaterial();
     EXPECT_NE(nullptr, mat);
 
     aiString name = mat->GetName();

+ 14 - 0
test/unit/utSTLImportExport.cpp

@@ -67,6 +67,20 @@ TEST_F( utSTLImporterExporter, importSTLFromFileTest ) {
     EXPECT_TRUE( importerTest() );
 }
 
+
+TEST_F(utSTLImporterExporter, test_multiple) {
+    // import same file twice, each with its own importer
+    // must work both times and not crash
+    Assimp::Importer importer1;
+    const aiScene *scene1 = importer1.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure );
+    EXPECT_NE(nullptr, scene1);
+
+    Assimp::Importer importer2;
+    const aiScene *scene2 = importer2.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure );
+    EXPECT_NE(nullptr, scene2);
+}
+
+
 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", aiProcess_ValidateDataStructure );