Przeglądaj źródła

Merge branch 'master' into fix_trivial_warnings

Kim Kulling 7 lat temu
rodzic
commit
d279a3cc02

+ 1 - 1
code/BlenderDNA.inl

@@ -585,7 +585,7 @@ template <> inline void Structure :: Convert<int>    (int& dest,const FileDataba
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-template <> inline void Structure :: Convert<short>  (short& dest,const FileDatabase& db) const
+template<> inline void Structure :: Convert<short>  (short& dest,const FileDatabase& db) const
 {
 {
     // automatic rescaling from short to float and vice versa (seems to be used by normals)
     // automatic rescaling from short to float and vice versa (seems to be used by normals)
     if (name == "float") {
     if (name == "float") {

+ 3 - 1
code/BlenderModifier.cpp

@@ -310,7 +310,9 @@ void  BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
 
 
     std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
     std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
     ai_assert(subd);
     ai_assert(subd);
-
+    if ( conv_data.meshes->empty() ) {
+        return;
+    }
     aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
     aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
     std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
     std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
 
 

+ 2 - 0
code/CMakeLists.txt

@@ -156,6 +156,8 @@ SET( Common_SRCS
   SkeletonMeshBuilder.h
   SkeletonMeshBuilder.h
   SplitByBoneCountProcess.cpp
   SplitByBoneCountProcess.cpp
   SplitByBoneCountProcess.h
   SplitByBoneCountProcess.h
+  ScaleProcess.cpp
+  ScaleProcess.h
   SmoothingGroups.h
   SmoothingGroups.h
   StandardShapes.cpp
   StandardShapes.cpp
   StandardShapes.h
   StandardShapes.h

+ 1 - 1
code/DeboneProcess.h

@@ -1,4 +1,4 @@
-                   /*
+/*
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 

+ 13 - 8
code/FindInvalidDataProcess.cpp

@@ -339,32 +339,37 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
 int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
 int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
 {
 {
     bool ret = false;
     bool ret = false;
-    std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false));
+    std::vector<bool> dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces);
 
 
     // Ignore elements that are not referenced by vertices.
     // Ignore elements that are not referenced by vertices.
     // (they are, for example, caused by the FindDegenerates step)
     // (they are, for example, caused by the FindDegenerates step)
-    for (unsigned int m = 0; m < pMesh->mNumFaces;++m)  {
+    for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) {
         const aiFace& f = pMesh->mFaces[m];
         const aiFace& f = pMesh->mFaces[m];
 
 
-        for (unsigned int i = 0; i < f.mNumIndices;++i) {
+        for (unsigned int i = 0; i < f.mNumIndices; ++i) {
             dirtyMask[f.mIndices[i]] = false;
             dirtyMask[f.mIndices[i]] = false;
         }
         }
     }
     }
 
 
     // Process vertex positions
     // Process vertex positions
-    if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask))    {
+    if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) {
         DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
         DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
+
         return 2;
         return 2;
     }
     }
 
 
     // process texture coordinates
     // process texture coordinates
-    for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i)    {
-        if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask))    {
+    for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) {
+        if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) {
+            pMesh->mNumUVComponents[i] = 0;
 
 
             // delete all subsequent texture coordinate sets.
             // delete all subsequent texture coordinate sets.
-            for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)  {
-                delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL;
+            for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+                delete[] pMesh->mTextureCoords[a];
+                pMesh->mTextureCoords[a] = NULL;
+                pMesh->mNumUVComponents[a] = 0;
             }
             }
+
             ret = true;
             ret = true;
         }
         }
     }
     }

+ 1 - 4
code/FixNormalsStep.h

@@ -56,14 +56,11 @@ namespace Assimp
  * vectors of an object are facing inwards. In this case they will be
  * vectors of an object are facing inwards. In this case they will be
  * flipped.
  * flipped.
  */
  */
-class FixInfacingNormalsProcess : public BaseProcess
-{
+class FixInfacingNormalsProcess : public BaseProcess {
 public:
 public:
-
     FixInfacingNormalsProcess();
     FixInfacingNormalsProcess();
     ~FixInfacingNormalsProcess();
     ~FixInfacingNormalsProcess();
 
 
-public:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Returns whether the processing step is present in the given flag field.
     /** Returns whether the processing step is present in the given flag field.
      * @param pFlags The processing flags the importer was called with. A bitwise
      * @param pFlags The processing flags the importer was called with. A bitwise

+ 51 - 101
code/IFCCurve.cpp

@@ -43,28 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Read profile and curves entities from IFC files
  *  @brief Read profile and curves entities from IFC files
  */
  */
 
 
-
-
 #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
 #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
 #include "IFCUtil.h"
 #include "IFCUtil.h"
 
 
 namespace Assimp {
 namespace Assimp {
-    namespace IFC {
-        namespace {
+namespace IFC {
+namespace {
 
 
 
 
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Conic is the base class for Circle and Ellipse
 // Conic is the base class for Circle and Ellipse
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class Conic : public Curve
-{
-
+class Conic : public Curve {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     Conic(const IfcConic& entity, ConversionData& conv)
     Conic(const IfcConic& entity, ConversionData& conv)
-        : Curve(entity,conv)
-    {
+    : Curve(entity,conv) {
         IfcMatrix4 trafo;
         IfcMatrix4 trafo;
         ConvertAxisPlacement(trafo,*entity.Position,conv);
         ConvertAxisPlacement(trafo,*entity.Position,conv);
 
 
@@ -75,8 +69,6 @@ public:
         p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
         p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     bool IsClosed() const {
     bool IsClosed() const {
         return true;
         return true;
@@ -84,7 +76,8 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
 
 
         a *= conv.angle_scale;
         a *= conv.angle_scale;
         b *= conv.angle_scale;
         b *= conv.angle_scale;
@@ -104,15 +97,11 @@ protected:
     IfcVector3 location, p[3];
     IfcVector3 location, p[3];
 };
 };
 
 
-
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Circle
 // Circle
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class Circle : public Conic
-{
-
+class Circle : public Conic {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     Circle(const IfcCircle& entity, ConversionData& conv)
     Circle(const IfcCircle& entity, ConversionData& conv)
         : Conic(entity,conv)
         : Conic(entity,conv)
@@ -120,8 +109,6 @@ public:
     {
     {
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcVector3 Eval(IfcFloat u) const {
     IfcVector3 Eval(IfcFloat u) const {
         u = -conv.angle_scale * u;
         u = -conv.angle_scale * u;
@@ -137,20 +124,15 @@ private:
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Ellipse
 // Ellipse
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class Ellipse : public Conic
-{
-
+class Ellipse : public Conic {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     Ellipse(const IfcEllipse& entity, ConversionData& conv)
     Ellipse(const IfcEllipse& entity, ConversionData& conv)
-        : Conic(entity,conv)
-        , entity(entity)
-    {
+    : Conic(entity,conv)
+    , entity(entity) {
+        // empty
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcVector3 Eval(IfcFloat u) const {
     IfcVector3 Eval(IfcFloat u) const {
         u = -conv.angle_scale * u;
         u = -conv.angle_scale * u;
@@ -162,25 +144,18 @@ private:
     const IfcEllipse& entity;
     const IfcEllipse& entity;
 };
 };
 
 
-
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Line
 // Line
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class Line : public Curve
-{
-
+class Line : public Curve {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     Line(const IfcLine& entity, ConversionData& conv)
     Line(const IfcLine& entity, ConversionData& conv)
-        : Curve(entity,conv)
-    {
+    : Curve(entity,conv) {
         ConvertCartesianPoint(p,entity.Pnt);
         ConvertCartesianPoint(p,entity.Pnt);
         ConvertVector(v,entity.Dir);
         ConvertVector(v,entity.Dir);
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     bool IsClosed() const {
     bool IsClosed() const {
         return false;
         return false;
@@ -193,16 +168,17 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
         // two points are always sufficient for a line segment
         // two points are always sufficient for a line segment
         return a==b ? 1 : 2;
         return a==b ? 1 : 2;
     }
     }
 
 
 
 
     // --------------------------------------------------
     // --------------------------------------------------
-    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
-    {
-        ai_assert(InRange(a) && InRange(b));
+    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
 
 
         if (a == b) {
         if (a == b) {
             out.verts.push_back(Eval(a));
             out.verts.push_back(Eval(a));
@@ -227,18 +203,14 @@ private:
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // CompositeCurve joins multiple smaller, bounded curves
 // CompositeCurve joins multiple smaller, bounded curves
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class CompositeCurve : public BoundedCurve
-{
-
+class CompositeCurve : public BoundedCurve {
     typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;
     typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;
 
 
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
     CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
-        : BoundedCurve(entity,conv)
-        , total()
-    {
+    : BoundedCurve(entity,conv)
+    , total() {
         curves.reserve(entity.Segments.size());
         curves.reserve(entity.Segments.size());
         for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) {
         for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) {
             // according to the specification, this must be a bounded curve
             // according to the specification, this must be a bounded curve
@@ -263,8 +235,6 @@ public:
         }
         }
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcVector3 Eval(IfcFloat u) const {
     IfcVector3 Eval(IfcFloat u) const {
         if (curves.empty()) {
         if (curves.empty()) {
@@ -287,7 +257,8 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
         size_t cnt = 0;
         size_t cnt = 0;
 
 
         IfcFloat acc = 0;
         IfcFloat acc = 0;
@@ -306,9 +277,9 @@ public:
     }
     }
 
 
     // --------------------------------------------------
     // --------------------------------------------------
-    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
-    {
-        ai_assert(InRange(a) && InRange(b));
+    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
 
 
         const size_t cnt = EstimateSampleCount(a,b);
         const size_t cnt = EstimateSampleCount(a,b);
         out.verts.reserve(out.verts.size() + cnt);
         out.verts.reserve(out.verts.size() + cnt);
@@ -330,19 +301,14 @@ public:
 
 
 private:
 private:
     std::vector< CurveEntry > curves;
     std::vector< CurveEntry > curves;
-
     IfcFloat total;
     IfcFloat total;
 };
 };
 
 
-
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // TrimmedCurve can be used to trim an unbounded curve to a bounded range
 // TrimmedCurve can be used to trim an unbounded curve to a bounded range
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class TrimmedCurve : public BoundedCurve
-{
-
+class TrimmedCurve : public BoundedCurve {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
     TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
         : BoundedCurve(entity,conv)
         : BoundedCurve(entity,conv)
@@ -409,8 +375,6 @@ public:
         ai_assert(maxval >= 0);
         ai_assert(maxval >= 0);
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcVector3 Eval(IfcFloat p) const {
     IfcVector3 Eval(IfcFloat p) const {
         ai_assert(InRange(p));
         ai_assert(InRange(p));
@@ -419,7 +383,8 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert( InRange( a ) );
+        ai_assert( InRange( b ) );
         return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
         return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
     }
     }
 
 
@@ -435,13 +400,11 @@ public:
     }
     }
 
 
 private:
 private:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcFloat TrimParam(IfcFloat f) const {
     IfcFloat TrimParam(IfcFloat f) const {
         return agree_sense ? f + range.first :  range.second - f;
         return agree_sense ? f + range.first :  range.second - f;
     }
     }
 
 
-
 private:
 private:
     ParamRange range;
     ParamRange range;
     IfcFloat maxval;
     IfcFloat maxval;
@@ -454,11 +417,8 @@ private:
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // PolyLine is a 'curve' defined by linear interpolation over a set of discrete points
 // PolyLine is a 'curve' defined by linear interpolation over a set of discrete points
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
-class PolyLine : public BoundedCurve
-{
-
+class PolyLine : public BoundedCurve {
 public:
 public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     PolyLine(const IfcPolyline& entity, ConversionData& conv)
     PolyLine(const IfcPolyline& entity, ConversionData& conv)
         : BoundedCurve(entity,conv)
         : BoundedCurve(entity,conv)
@@ -472,8 +432,6 @@ public:
         }
         }
     }
     }
 
 
-public:
-
     // --------------------------------------------------
     // --------------------------------------------------
     IfcVector3 Eval(IfcFloat p) const {
     IfcVector3 Eval(IfcFloat p) const {
         ai_assert(InRange(p));
         ai_assert(InRange(p));
@@ -502,13 +460,10 @@ private:
     std::vector<IfcVector3> points;
     std::vector<IfcVector3> points;
 };
 };
 
 
-
 } // anon
 } // anon
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
-{
+Curve* Curve::Convert(const IFC::IfcCurve& curve,ConversionData& conv) {
     if(curve.ToPtr<IfcBoundedCurve>()) {
     if(curve.ToPtr<IfcBoundedCurve>()) {
         if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
         if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
             return new PolyLine(*c,conv);
             return new PolyLine(*c,conv);
@@ -519,9 +474,6 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
         if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
         if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
             return new CompositeCurve(*c,conv);
             return new CompositeCurve(*c,conv);
         }
         }
-        //if(const IfcBSplineCurve* c = curve.ToPtr<IfcBSplineCurve>()) {
-        //  return new BSplineCurve(*c,conv);
-        //}
     }
     }
 
 
     if(curve.ToPtr<IfcConic>()) {
     if(curve.ToPtr<IfcConic>()) {
@@ -543,8 +495,7 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
 
 
 #ifdef ASSIMP_BUILD_DEBUG
 #ifdef ASSIMP_BUILD_DEBUG
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool Curve :: InRange(IfcFloat u) const
-{
+bool Curve::InRange(IfcFloat u) const {
     const ParamRange range = GetParametricRange();
     const ParamRange range = GetParametricRange();
     if (IsClosed()) {
     if (IsClosed()) {
         return true;
         return true;
@@ -555,25 +506,24 @@ bool Curve :: InRange(IfcFloat u) const
 #endif
 #endif
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-IfcFloat Curve :: GetParametricRangeDelta() const
-{
+IfcFloat Curve::GetParametricRangeDelta() const {
     const ParamRange& range = GetParametricRange();
     const ParamRange& range = GetParametricRange();
     return std::abs(range.second - range.first);
     return std::abs(range.second - range.first);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-size_t Curve :: EstimateSampleCount(IfcFloat a, IfcFloat b) const
-{
-    (void)(a); (void)(b);
-    ai_assert(InRange(a) && InRange(b));
+size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+    (void)(a); (void)(b);  
+    ai_assert( InRange( a ) );
+    ai_assert( InRange( b ) );
 
 
     // arbitrary default value, deriving classes should supply better suited values
     // arbitrary default value, deriving classes should supply better suited values
     return 16;
     return 16;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b, unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15)
-{
+IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b,
+        unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15) {
     ai_assert(samples>1);
     ai_assert(samples>1);
 
 
     const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
     const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
@@ -595,7 +545,8 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
         }
         }
     }
     }
 
 
-    ai_assert(min_diff[0] != inf && min_diff[1] != inf);
+    ai_assert( min_diff[ 0 ] != inf );
+    ai_assert( min_diff[ 1 ] != inf );
     if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
     if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
         return min_point[0];
         return min_point[0];
     }
     }
@@ -616,15 +567,15 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
+bool Curve::ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
 {
 {
     // note: the following algorithm is not guaranteed to find the 'right' parameter value
     // note: the following algorithm is not guaranteed to find the 'right' parameter value
     // in all possible cases, but it will always return at least some value so this function
     // in all possible cases, but it will always return at least some value so this function
     // will never fail in the default implementation.
     // will never fail in the default implementation.
 
 
     // XXX derive threshold from curve topology
     // XXX derive threshold from curve topology
-    const IfcFloat threshold = 1e-4f;
-    const unsigned int samples = 16;
+    static const IfcFloat threshold = 1e-4f;
+    static const unsigned int samples = 16;
 
 
     const ParamRange& range = GetParametricRange();
     const ParamRange& range = GetParametricRange();
     paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
     paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
@@ -633,9 +584,9 @@ bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
-{
-    ai_assert(InRange(a) && InRange(b));
+void Curve::SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
+    ai_assert( InRange( a ) );
+    ai_assert( InRange( b ) );
 
 
     const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
     const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
     out.verts.reserve( out.verts.size() + cnt + 1);
     out.verts.reserve( out.verts.size() + cnt + 1);
@@ -647,16 +598,15 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool BoundedCurve :: IsClosed() const
-{
+bool BoundedCurve::IsClosed() const {
     return false;
     return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BoundedCurve :: SampleDiscrete(TempMesh& out) const
-{
+void BoundedCurve::SampleDiscrete(TempMesh& out) const {
     const ParamRange& range = GetParametricRange();
     const ParamRange& range = GetParametricRange();
-    ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
+    ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
+    ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
 
 
     return SampleDiscrete(out,range.first,range.second);
     return SampleDiscrete(out,range.first,range.second);
 }
 }

+ 8 - 12
code/LineSplitter.h

@@ -69,27 +69,23 @@ for(LineSplitter splitter(stream);splitter;++splitter) {
 
 
     std::cout << "Current line is: " << splitter.get_index() << std::endl;
     std::cout << "Current line is: " << splitter.get_index() << std::endl;
 }
 }
-@endcode */
+@endcode
+*/
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-class LineSplitter
-{
+class LineSplitter {
 public:
 public:
-
     typedef size_t line_idx;
     typedef size_t line_idx;
 
 
-public:
-
     // -----------------------------------------
     // -----------------------------------------
     /** construct from existing stream reader
     /** construct from existing stream reader
     note: trim is *always* assumed true if skyp_empty_lines==true
     note: trim is *always* assumed true if skyp_empty_lines==true
     */
     */
     LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
     LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
-        : idx( 0 )
-        , stream(stream)
-        , swallow()
-        , skip_empty_lines(skip_empty_lines)
-        , trim(trim)
-    {
+    : idx( 0 )
+    , stream(stream)
+    , swallow()
+    , skip_empty_lines(skip_empty_lines)
+    , trim(trim) {
         cur.reserve(1024);
         cur.reserve(1024);
         operator++();
         operator++();
 
 

+ 1 - 3
code/RemoveVCProcess.h

@@ -54,8 +54,7 @@ namespace Assimp {
 /** RemoveVCProcess: Class to exclude specific parts of the data structure
 /** RemoveVCProcess: Class to exclude specific parts of the data structure
  *  from further processing by removing them,
  *  from further processing by removing them,
 */
 */
-class ASSIMP_API RemoveVCProcess : public BaseProcess
-{
+class ASSIMP_API RemoveVCProcess : public BaseProcess {
 public:
 public:
     /// The default class constructor.
     /// The default class constructor.
     RemoveVCProcess();
     RemoveVCProcess();
@@ -63,7 +62,6 @@ public:
     /// The class destructor.
     /// The class destructor.
     ~RemoveVCProcess();
     ~RemoveVCProcess();
 
 
-public:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Returns whether the processing step is present in the given flag field.
     /** Returns whether the processing step is present in the given flag field.
     * @param pFlags The processing flags the importer was called with. A bitwise
     * @param pFlags The processing flags the importer was called with. A bitwise

+ 1 - 1
code/STEPFile.h

@@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //
 //
 #if _MSC_VER > 1500 || (defined __GNUC___)
 #if _MSC_VER > 1500 || (defined __GNUC___)
 #   define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
 #   define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
-#   else
+#else
 #   define step_unordered_map map
 #   define step_unordered_map map
 #   define step_unordered_multimap multimap
 #   define step_unordered_multimap multimap
 #endif
 #endif

+ 105 - 0
code/ScaleProcess.cpp

@@ -0,0 +1,105 @@
+/*
+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 "ScaleProcess.h"
+
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+
+namespace Assimp {
+
+ScaleProcess::ScaleProcess()
+: BaseProcess()
+, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
+    // empty
+}
+
+ScaleProcess::~ScaleProcess() {
+    // empty
+}
+
+void ScaleProcess::setScale( ai_real scale ) {
+    mScale = scale;
+}
+
+ai_real ScaleProcess::getScale() const {
+    return mScale;
+}
+
+bool ScaleProcess::IsActive( unsigned int pFlags ) const {
+    return ( pFlags & aiProcess_GlobalScale ) != 0;
+}
+
+void ScaleProcess::SetupProperties( const Importer* pImp ) {
+    mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 0 );
+}
+
+void ScaleProcess::Execute( aiScene* pScene ) {
+    if ( nullptr == pScene ) {
+        return;
+    }
+
+    if ( nullptr == pScene->mRootNode ) {
+        return;
+    }
+
+    traverseNodes( pScene->mRootNode );
+}
+
+void ScaleProcess::traverseNodes( aiNode *node ) {
+    applyScaling( node );
+
+    /*for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
+        aiNode *currentNode = currentNode->mChildren[ i ];
+        if ( nullptr != currentNode ) {
+            traverseNodes( currentNode );
+        }
+    }*/
+}
+
+void ScaleProcess::applyScaling( aiNode *currentNode ) {
+    if ( nullptr != currentNode ) {
+        currentNode->mTransformation.a1 = currentNode->mTransformation.a1 * mScale;
+        currentNode->mTransformation.b2 = currentNode->mTransformation.b2 * mScale;
+        currentNode->mTransformation.c3 = currentNode->mTransformation.c3 * mScale;
+    }
+}
+
+} // Namespace Assimp

+ 87 - 0
code/ScaleProcess.h

@@ -0,0 +1,87 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include "BaseProcess.h"
+
+struct aiNode;
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+#   define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT  1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** ScaleProcess: Class to rescale the whole model.
+*/
+class ASSIMP_API ScaleProcess : public BaseProcess {
+public:
+    /// The default class constructor.
+    ScaleProcess();
+
+    /// The class destructor.
+    virtual ~ScaleProcess();
+
+    /// Will set the scale manually.
+    void setScale( ai_real scale );
+
+    /// Returns the current scaling value.
+    ai_real getScale() const;
+
+    /// Overwritten, @see BaseProcess
+    virtual bool IsActive( unsigned int pFlags ) const;
+
+    /// Overwritten, @see BaseProcess
+    virtual void SetupProperties( const Importer* pImp );
+
+    /// Overwritten, @see BaseProcess
+    virtual void Execute( aiScene* pScene );
+
+private:
+    void traverseNodes( aiNode *currentNode );
+    void applyScaling( aiNode *currentNode );
+
+private:
+    ai_real mScale;
+};
+
+} // Namespace Assimp

+ 6 - 6
code/glTF2Exporter.cpp

@@ -446,15 +446,15 @@ void glTF2Exporter::ExportMaterials()
             ) {
             ) {
                 // convert specular color to luminance
                 // convert specular color to luminance
                 float specularIntensity = specularColor[0] * 0.2125 + specularColor[1] * 0.7154 + specularColor[2] * 0.0721;
                 float specularIntensity = specularColor[0] * 0.2125 + specularColor[1] * 0.7154 + specularColor[2] * 0.0721;
-                float roughnessFactor = 1 - std::sqrt(shininess / 1000);
-
-                roughnessFactor = std::pow(roughnessFactor, 2);
-                roughnessFactor = std::min(std::max(roughnessFactor, 0.0f), 1.0f);
+                //normalize shininess (assuming max is 1000) with an inverse exponentional curve
+                float normalizedShininess = std::sqrt(shininess / 1000);
 
 
+                //clamp the shininess value between 0 and 1
+                normalizedShininess = std::min(std::max(normalizedShininess, 0.0f), 1.0f);
                 // low specular intensity values should produce a rough material even if shininess is high.
                 // low specular intensity values should produce a rough material even if shininess is high.
-                roughnessFactor = 1 - (roughnessFactor * specularIntensity);
+                normalizedShininess = normalizedShininess * specularIntensity;
 
 
-                m->pbrMetallicRoughness.roughnessFactor = roughnessFactor;
+                m->pbrMetallicRoughness.roughnessFactor = 1 - normalizedShininess;
             }
             }
         }
         }
 
 

+ 8 - 0
include/assimp/config.h.in

@@ -933,6 +933,14 @@ enum aiComponent
 
 
 #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
 #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
 
 
+/**
+ *  @brief  Specifies a gobal key factor for scale, float value
+ */
+#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+#   define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT  1.0f
+#endif // !! AI_DEBONE_THRESHOLD
 
 
 // ---------- All the Build/Compile-time defines ------------
 // ---------- All the Build/Compile-time defines ------------
 
 

+ 11 - 1
include/assimp/postprocess.h

@@ -525,7 +525,17 @@ enum aiPostProcessSteps
      *  Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
      *  Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
      *  only if all bones within the scene qualify for removal.
      *  only if all bones within the scene qualify for removal.
     */
     */
-    aiProcess_Debone  = 0x4000000
+    aiProcess_Debone  = 0x4000000,
+
+    // -------------------------------------------------------------------------
+    /** <hr>This step will perform a global scale of the model.
+    *
+    *  Some importers are providing a mechanism to define a scaling unit for the
+    *  model. This post processing step can be used to do so.
+    *
+    *  Use <tt>#AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY</tt> to control this.
+    */
+    aiProcess_GlobalScale = 0x8000000
 
 
     // aiProcess_GenEntityMeshes = 0x100000,
     // aiProcess_GenEntityMeshes = 0x100000,
     // aiProcess_OptimizeAnimations = 0x200000
     // aiProcess_OptimizeAnimations = 0x200000

+ 3 - 0
port/PyAssimp/pyassimp/helper.py

@@ -30,6 +30,9 @@ if os.name=='posix':
     additional_dirs.append('/usr/lib/x86_64-linux-gnu')
     additional_dirs.append('/usr/lib/x86_64-linux-gnu')
     additional_dirs.append('/usr/local/lib/')
     additional_dirs.append('/usr/local/lib/')
 
 
+    if 'LD_LIBRARY_PATH' in os.environ:
+        additional_dirs.extend([item for item in os.environ['LD_LIBRARY_PATH'].split(':') if item])
+
     # check if running from anaconda.
     # check if running from anaconda.
     if "conda" or "continuum" in sys.version.lower():
     if "conda" or "continuum" in sys.version.lower():
       cur_path = get_python_lib()
       cur_path = get_python_lib()

+ 9 - 3
test/CMakeLists.txt

@@ -114,8 +114,6 @@ SET( TEST_SRCS
   unit/utPMXImporter.cpp
   unit/utPMXImporter.cpp
   unit/utRemoveComments.cpp
   unit/utRemoveComments.cpp
   unit/utRemoveComponent.cpp
   unit/utRemoveComponent.cpp
-  unit/utRemoveRedundantMaterials.cpp
-  unit/utRemoveVCProcess.cpp
   unit/utScenePreprocessor.cpp
   unit/utScenePreprocessor.cpp
   unit/utSceneCombiner.cpp
   unit/utSceneCombiner.cpp
   unit/utSharedPPData.cpp
   unit/utSharedPPData.cpp
@@ -135,8 +133,15 @@ SET( TEST_SRCS
   unit/utQ3DImportExport.cpp
   unit/utQ3DImportExport.cpp
   unit/utProfiler.cpp
   unit/utProfiler.cpp
 )
 )
+SET( POST_PROCESSES
+  unit/utRemoveRedundantMaterials.cpp
+  unit/utRemoveVCProcess.cpp
+  unit/utScaleProcess.cpp
+  unit/utJoinVertices.cpp
+)
 
 
-SOURCE_GROUP( tests FILES  ${TEST_SRCS} )
+SOURCE_GROUP( tests             FILES  ${TEST_SRCS} )
+SOURCE_GROUP( tests/PostProcess FILES  ${POST_PROCESSES})
 
 
 add_executable( unit
 add_executable( unit
     ../contrib/gtest/src/gtest-all.cc
     ../contrib/gtest/src/gtest-all.cc
@@ -144,6 +149,7 @@ add_executable( unit
     unit/Main.cpp
     unit/Main.cpp
     ../code/Version.cpp
     ../code/Version.cpp
     ${TEST_SRCS}
     ${TEST_SRCS}
+    ${POST_PROCESSES}
 )
 )
 
 
 add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models")
 add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models")

+ 7 - 1
test/unit/TestModelFactory.h

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 #include <assimp/scene.h>
 #include <assimp/scene.h>
+#include <assimp/mesh.h>
 #include <assimp/material.h>
 #include <assimp/material.h>
 
 
 namespace Assimp {
 namespace Assimp {
@@ -57,7 +58,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    static aiScene *createDefaultTestModel( float &opacity  ) {
+    static aiScene *createDefaultTestModel( float &opacity ) {
         aiScene *scene( new aiScene );
         aiScene *scene( new aiScene );
         scene->mNumMaterials = 1;
         scene->mNumMaterials = 1;
         scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
         scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
@@ -93,6 +94,11 @@ public:
 
 
         return scene;
         return scene;
     }
     }
+
+    static void releaseDefaultTestModel( aiScene **scene ) {
+        delete *scene;
+        *scene = nullptr;
+    }
 };
 };
 
 
 }
 }

+ 85 - 0
test/unit/utScaleProcess.cpp

@@ -0,0 +1,85 @@
+/*
+---------------------------------------------------------------------------
+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 "ScaleProcess.h"
+#include "TestModelFactory.h"
+
+namespace Assimp {
+namespace UnitTest {
+
+class utScaleProcess : public ::testing::Test {
+    // empty
+};
+
+TEST_F( utScaleProcess, createTest ) {
+    bool ok = true;
+    try {
+        ScaleProcess process;
+    } catch ( ... ) {
+        ok = false;
+    }
+    EXPECT_TRUE( ok );
+}
+
+TEST_F( utScaleProcess, accessScaleTest ) {
+    ScaleProcess process;
+    EXPECT_FLOAT_EQ( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT, process.getScale() );
+
+    process.setScale( 2.0f );
+    EXPECT_FLOAT_EQ( 2.0f, process.getScale() );
+}
+
+TEST_F( utScaleProcess, rescaleModelTest ) {
+    float opacity;
+    aiScene *testScene = TestModelFacttory::createDefaultTestModel( opacity );
+    ai_real v1 = testScene->mRootNode->mTransformation.a1;
+    ScaleProcess process;
+    process.setScale( 10.0f );
+    process.Execute( testScene );
+    ai_real v2 = testScene->mRootNode->mTransformation.a1;
+    const ai_real scale = v2 / v1;
+    EXPECT_FLOAT_EQ( scale, 10.0f );
+    TestModelFacttory::releaseDefaultTestModel( &testScene );
+}
+
+} // Namespace UnitTest
+} // Namespace Assimp