ソースを参照

Merge pull request #1732 from turol/threadsafe

Fix thread-safety issue in 3DS and ASE loaders
turol 7 年 前
コミット
1b1d1e7376
6 ファイル変更132 行追加29 行削除
  1. 1 2
      code/3DSConverter.cpp
  2. 69 7
      code/3DSHelper.h
  3. 9 9
      code/3DSLoader.cpp
  4. 6 7
      code/ASELoader.cpp
  5. 2 2
      code/ASEParser.cpp
  6. 45 2
      code/ASEParser.h

+ 1 - 2
code/3DSConverter.cpp

@@ -127,9 +127,8 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
     if (cnt && idx == mScene->mMaterials.size())
     {
         // We need to create our own default material
-        D3DS::Material sMat;
+        D3DS::Material sMat("%%%DEFAULT");
         sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
-        sMat.mName = "%%%DEFAULT";
         mScene->mMaterials.push_back(sMat);
 
         DefaultLogger::get()->info("3DS: Generating default material");

+ 69 - 7
code/3DSHelper.h

@@ -370,9 +370,14 @@ struct Texture
 /** Helper structure representing a 3ds material */
 struct Material
 {
-    //! Default constructor. Builds a default name for the material
-    Material()
-    : mDiffuse            ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
+    //! Default constructor has been deleted
+    Material() = delete;
+
+
+    //! Constructor with explicit name
+    explicit Material(const std::string &name)
+    : mName(name)
+    , mDiffuse            ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
     , mSpecularExponent   ( ai_real( 0.0 ) )
     , mShininessStrength  ( ai_real( 1.0 ) )
     , mShading(Discreet3DS::Gouraud)
@@ -380,13 +385,70 @@ struct Material
     , mBumpHeight         ( ai_real( 1.0 ) )
     , mTwoSided           (false)
     {
-        static int iCnt = 0;
+    }
 
-        char szTemp[128];
-        ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
+
+    Material(const Material &other)            = default;
+    Material &operator=(const Material &other) = default;
+
+
+    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
+    Material(Material &&other)
+    : mName(std::move(other.mName))
+    , mDiffuse(std::move(other.mDiffuse))
+    , mSpecularExponent(std::move(other.mSpecularExponent))
+    , mShininessStrength(std::move(other.mShininessStrength))
+    , mSpecular(std::move(other.mSpecular))
+    , mAmbient(std::move(other.mAmbient))
+    , mShading(std::move(other.mShading))
+    , mTransparency(std::move(other.mTransparency))
+    , sTexDiffuse(std::move(other.sTexDiffuse))
+    , sTexOpacity(std::move(other.sTexOpacity))
+    , sTexSpecular(std::move(other.sTexSpecular))
+    , sTexReflective(std::move(other.sTexReflective))
+    , sTexBump(std::move(other.sTexBump))
+    , sTexEmissive(std::move(other.sTexEmissive))
+    , sTexShininess(std::move(other.sTexShininess))
+    , mBumpHeight(std::move(other.mBumpHeight))
+    , mEmissive(std::move(other.mEmissive))
+    , sTexAmbient(std::move(other.sTexAmbient))
+    , mTwoSided(std::move(other.mTwoSided))
+    {
     }
 
+
+    Material &operator=(Material &&other) {
+        if (this == &other) {
+            return *this;
+        }
+
+        mName = std::move(other.mName);
+        mDiffuse = std::move(other.mDiffuse);
+        mSpecularExponent = std::move(other.mSpecularExponent);
+        mShininessStrength = std::move(other.mShininessStrength),
+        mSpecular = std::move(other.mSpecular);
+        mAmbient = std::move(other.mAmbient);
+        mShading = std::move(other.mShading);
+        mTransparency = std::move(other.mTransparency);
+        sTexDiffuse = std::move(other.sTexDiffuse);
+        sTexOpacity = std::move(other.sTexOpacity);
+        sTexSpecular = std::move(other.sTexSpecular);
+        sTexReflective = std::move(other.sTexReflective);
+        sTexBump = std::move(other.sTexBump);
+        sTexEmissive = std::move(other.sTexEmissive);
+        sTexShininess = std::move(other.sTexShininess);
+        mBumpHeight = std::move(other.mBumpHeight);
+        mEmissive = std::move(other.mEmissive);
+        sTexAmbient = std::move(other.sTexAmbient);
+        mTwoSided = std::move(other.mTwoSided);
+
+        return *this;
+    }
+
+
+    ~Material() {}
+
+
     //! Name of the material
     std::string mName;
     //! Diffuse color of the material

+ 9 - 9
code/3DSLoader.cpp

@@ -105,14 +105,14 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 Discreet3DSImporter::Discreet3DSImporter()
-    : stream(),
-    mLastNodeIndex(),
-    mCurrentNode(),
-    mRootNode(),
-    mScene(),
-    mMasterScale(),
-    bHasBG(),
-    bIsPrj()
+: stream()
+, mLastNodeIndex()
+, mCurrentNode()
+, mRootNode()
+, mScene()
+, mMasterScale()
+, bHasBG()
+, bIsPrj()
 {}
 
 // ------------------------------------------------------------------------------------------------
@@ -346,7 +346,7 @@ void Discreet3DSImporter::ParseObjectChunk()
     case Discreet3DS::CHUNK_MAT_MATERIAL:
 
         // Add a new material to the list
-        mScene->mMaterials.push_back(D3DS::Material());
+        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + std::to_string(mScene->mMaterials.size()))));
         ParseMaterialChunk();
         break;
 

+ 6 - 7
code/ASELoader.cpp

@@ -83,11 +83,11 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 ASEImporter::ASEImporter()
-    : mParser(),
-    mBuffer(),
-    pcScene(),
-    configRecomputeNormals(),
-    noSkeletonMesh()
+: mParser()
+, mBuffer()
+, pcScene()
+, configRecomputeNormals()
+, noSkeletonMesh()
 {}
 
 // ------------------------------------------------------------------------------------------------
@@ -276,14 +276,13 @@ void ASEImporter::GenerateDefaultMaterial()
     }
     if (bHas || mParser->m_vMaterials.empty())  {
         // add a simple material without submaterials to the parser's list
-        mParser->m_vMaterials.push_back ( ASE::Material() );
+        mParser->m_vMaterials.push_back ( ASE::Material(AI_DEFAULT_MATERIAL_NAME) );
         ASE::Material& mat = mParser->m_vMaterials.back();
 
         mat.mDiffuse  = aiColor3D(0.6f,0.6f,0.6f);
         mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
         mat.mAmbient  = aiColor3D(0.05f,0.05f,0.05f);
         mat.mShading  = Discreet3DS::Gouraud;
-        mat.mName     = AI_DEFAULT_MATERIAL_NAME;
     }
 }
 

+ 2 - 2
code/ASEParser.cpp

@@ -528,7 +528,7 @@ void Parser::ParseLV1MaterialListBlock()
                 ParseLV4MeshLong(iMaterialCount);
 
                 // now allocate enough storage to hold all materials
-                m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
+                m_vMaterials.resize(iOldMaterialCount+iMaterialCount, Material("INVALID"));
                 continue;
             }
             if (TokenMatch(filePtr,"MATERIAL",8))
@@ -706,7 +706,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
                 ParseLV4MeshLong(iNumSubMaterials);
 
                 // allocate enough storage
-                mat.avSubMaterials.resize(iNumSubMaterials);
+                mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL"));
             }
             // submaterial chunks
             if (TokenMatch(filePtr,"SUBMATERIAL",11))

+ 45 - 2
code/ASEParser.h

@@ -67,10 +67,53 @@ using namespace D3DS;
 /** Helper structure representing an ASE material */
 struct Material : public D3DS::Material
 {
-    //! Default constructor
-    Material() : pcInstance(NULL), bNeed (false)
+    //! Default constructor has been deleted
+    Material() = delete;
+
+
+    //! Constructor with explicit name
+    explicit Material(const std::string &name)
+    : D3DS::Material(name)
+    , pcInstance(NULL)
+    , bNeed (false)
     {}
 
+
+    Material(const Material &other)            = default;
+    Material &operator=(const Material &other) = default;
+
+
+    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
+    Material(Material &&other)
+    : D3DS::Material(std::move(other))
+    , avSubMaterials(std::move(other.avSubMaterials))
+    , pcInstance(std::move(other.pcInstance))
+    , bNeed(std::move(other.bNeed))
+    {
+        other.pcInstance = nullptr;
+    }
+
+
+    Material &operator=(Material &&other) {
+        if (this == &other) {
+            return *this;
+        }
+
+        D3DS::Material::operator=(std::move(other));
+
+        avSubMaterials = std::move(other.avSubMaterials);
+        pcInstance = std::move(other.pcInstance);
+        bNeed = std::move(other.bNeed);
+
+        other.pcInstance = nullptr;
+
+        return *this;
+    }
+
+
+    ~Material() {}
+
+
     //! Contains all sub materials of this material
     std::vector<Material> avSubMaterials;