Prevent assert during path animation 07/50007/5
authorLee Morgan <Lee.morgan@partner.samsung.com>
Thu, 22 Oct 2015 15:37:30 +0000 (16:37 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 27 Oct 2015 10:09:10 +0000 (10:09 +0000)
Change-Id: I131e8e79a9e965eed2b8a56f2d177abdd5bd2199

dali/internal/event/animation/path-impl.cpp
dali/internal/event/animation/path-impl.h
dali/internal/update/animation/scene-graph-animator.h

index afd9d99..2e00c87 100644 (file)
@@ -62,7 +62,6 @@ const float BezierBasisCoeff[] = {  -1.0f,  3.0f, -3.0f, 1.0f,
 
 const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff );
 
-
 Dali::BaseHandle Create()
 {
   return Dali::Path::New();
@@ -70,6 +69,11 @@ Dali::BaseHandle Create()
 
 Dali::TypeRegistration mType( typeid(Dali::Path), typeid(Dali::Handle), Create );
 
+inline bool PathIsComplete(const Dali::Vector<Vector3>& point, const Dali::Vector<Vector3>& controlPoint)
+{
+  return ( point.Size() > 1 && controlPoint.Size() == (point.Size()-1)*2 );
+}
+
 } //Unnamed namespace
 
 Path* Path::New()
@@ -346,161 +350,184 @@ void Path::FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal
 
 void Path::Sample( float t, Vector3& position, Vector3& tangent ) const
 {
-  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
-
-  unsigned int segment;
-  float tLocal;
-  FindSegmentAndProgress( t, segment, tLocal );
-
-  //Get points and control points in the segment
-  const Vector3& controlPoint0 = mControlPoint[2*segment];
-  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
-  const Vector3& point0 = mPoint[segment];
-  const Vector3& point1 = mPoint[segment+1];
-
-  if(tLocal < Math::MACHINE_EPSILON_1)
+  if( !SampleAt(t, position, tangent) )
   {
-    position = point0;
-    tangent = ( controlPoint0 - point0 ) * 3.0f;
-    tangent.Normalize();
+    DALI_ASSERT_ALWAYS(!"Spline not fully initialized" );
   }
-  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
-  {
-    position = point1;
-    tangent = ( point1 - controlPoint1 ) * 3.0f;
-    tangent.Normalize();
-  }
-  else
+}
+
+bool Path::SampleAt( float t, Vector3& position, Vector3& tangent ) const
+{
+  bool done = false;
+
+  if( PathIsComplete(mPoint, mControlPoint) )
   {
-    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
-    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+    unsigned int segment;
+    float tLocal;
+    FindSegmentAndProgress( t, segment, tLocal );
 
-    //X
-    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+    //Get points and control points in the segment
+    const Vector3& controlPoint0 = mControlPoint[2*segment];
+    const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+    const Vector3& point0 = mPoint[segment];
+    const Vector3& point1 = mPoint[segment+1];
 
-    Vector4 A = BezierBasis * cVect;
-    position.x = sVect.Dot4(A);
-    tangent.x  = sVectDerivative.Dot(Vector3(A));
+    if(tLocal < Math::MACHINE_EPSILON_1)
+    {
+      position = point0;
+      tangent = ( controlPoint0 - point0 ) * 3.0f;
+      tangent.Normalize();
+    }
+    else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+    {
+      position = point1;
+      tangent = ( point1 - controlPoint1 ) * 3.0f;
+      tangent.Normalize();
+    }
+    else
+    {
+      const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+      const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
 
-    //Y
-    cVect.x  = point0.y;
-    cVect.y  = controlPoint0.y;
-    cVect.z  = controlPoint1.y;
-    cVect.w  = point1.y;
+      //X
+      Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
 
-    A = BezierBasis * cVect;
-    position.y = sVect.Dot4(A);
-    tangent.y  = sVectDerivative.Dot(Vector3(A));
+      Vector4 A = BezierBasis * cVect;
+      position.x = sVect.Dot4(A);
+      tangent.x  = sVectDerivative.Dot(Vector3(A));
 
-    //Z
-    cVect.x  = point0.z;
-    cVect.y  = controlPoint0.z;
-    cVect.z  = controlPoint1.z;
-    cVect.w  = point1.z;
+      //Y
+      cVect.x  = point0.y;
+      cVect.y  = controlPoint0.y;
+      cVect.z  = controlPoint1.y;
+      cVect.w  = point1.y;
 
-    A = BezierBasis * cVect;
-    position.z = sVect.Dot4(A);
-    tangent.z  = sVectDerivative.Dot(Vector3(A));
+      A = BezierBasis * cVect;
+      position.y = sVect.Dot4(A);
+      tangent.y  = sVectDerivative.Dot(Vector3(A));
 
-    tangent.Normalize();
+      //Z
+      cVect.x  = point0.z;
+      cVect.y  = controlPoint0.z;
+      cVect.z  = controlPoint1.z;
+      cVect.w  = point1.z;
+
+      A = BezierBasis * cVect;
+      position.z = sVect.Dot4(A);
+      tangent.z  = sVectDerivative.Dot(Vector3(A));
+
+      tangent.Normalize();
+    }
+
+    done = true;
   }
+
+  return done;
 }
 
-Vector3 Path::SamplePosition( float t ) const
+bool Path::SamplePosition( float t, Vector3& position ) const
 {
-  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+  bool done = false;
 
-  unsigned int segment;
-  float tLocal;
-  FindSegmentAndProgress( t, segment, tLocal );
+  if( PathIsComplete(mPoint, mControlPoint) )
+  {
+    unsigned int segment;
+    float tLocal;
+    FindSegmentAndProgress( t, segment, tLocal );
 
-  const Vector3& controlPoint0 = mControlPoint[2*segment];
-  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
-  const Vector3& point0 = mPoint[segment];
-  const Vector3& point1 = mPoint[segment+1];
+    const Vector3& controlPoint0 = mControlPoint[2*segment];
+    const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+    const Vector3& point0 = mPoint[segment];
+    const Vector3& point1 = mPoint[segment+1];
 
-  Vector3 position;
-  if(tLocal < Math::MACHINE_EPSILON_1)
-  {
-    position = point0;
-  }
-  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
-  {
-    position = point1;
-  }
-  else
-  {
-    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
-
-    //X
-    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
-    position.x = sVect.Dot4(BezierBasis * cVect);
-
-    //Y
-    cVect.x  = point0.y;
-    cVect.y  = controlPoint0.y;
-    cVect.z  = controlPoint1.y;
-    cVect.w  = point1.y;
-    position.y = sVect.Dot4(BezierBasis * cVect);
-
-    //Z
-    cVect.x  = point0.z;
-    cVect.y  = controlPoint0.z;
-    cVect.z  = controlPoint1.z;
-    cVect.w  = point1.z;
-    position.z = sVect.Dot4(BezierBasis * cVect);
+    if(tLocal < Math::MACHINE_EPSILON_1)
+    {
+      position = point0;
+    }
+    else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+    {
+      position = point1;
+    }
+    else
+    {
+      const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+
+      //X
+      Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+      position.x = sVect.Dot4(BezierBasis * cVect);
+
+      //Y
+      cVect.x  = point0.y;
+      cVect.y  = controlPoint0.y;
+      cVect.z  = controlPoint1.y;
+      cVect.w  = point1.y;
+      position.y = sVect.Dot4(BezierBasis * cVect);
+
+      //Z
+      cVect.x  = point0.z;
+      cVect.y  = controlPoint0.z;
+      cVect.z  = controlPoint1.z;
+      cVect.w  = point1.z;
+      position.z = sVect.Dot4(BezierBasis * cVect);
+    }
+
+    done = true;
   }
 
-  return position;
+  return done;
 }
 
-Vector3 Path::SampleTangent( float t ) const
+bool Path::SampleTangent( float t, Vector3& tangent ) const
 {
-  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+  bool done = false;
 
-  unsigned int segment;
-  float tLocal;
-  FindSegmentAndProgress( t, segment, tLocal );
+  if( PathIsComplete(mPoint, mControlPoint) )
+  {
+    unsigned int segment;
+    float tLocal;
+    FindSegmentAndProgress( t, segment, tLocal );
 
-  const Vector3& controlPoint0 = mControlPoint[2*segment];
-  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
-  const Vector3& point0 = mPoint[segment];
-  const Vector3& point1 = mPoint[segment+1];
+    const Vector3& controlPoint0 = mControlPoint[2*segment];
+    const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+    const Vector3& point0 = mPoint[segment];
+    const Vector3& point1 = mPoint[segment+1];
 
-  Vector3 tangent;
-  if(tLocal < Math::MACHINE_EPSILON_1)
-  {
-    tangent = ( controlPoint0 - point0 ) * 3.0f;
-  }
-  else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
-  {
-    tangent = ( point1 - controlPoint1 ) * 3.0f;
-  }
-  else
-  {
-    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
-
-    //X
-    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
-    tangent.x  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
-
-    //Y
-    cVect.x  = point0.y;
-    cVect.y  = controlPoint0.y;
-    cVect.z  = controlPoint1.y;
-    cVect.w  = point1.y;
-    tangent.y  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
-
-    //Z
-    cVect.x  = point0.z;
-    cVect.y  = controlPoint0.z;
-    cVect.z  = controlPoint1.z;
-    cVect.w  = point1.z;
-    tangent.z  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+    if(tLocal < Math::MACHINE_EPSILON_1)
+    {
+      tangent = ( controlPoint0 - point0 ) * 3.0f;
+    }
+    else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
+    {
+      tangent = ( point1 - controlPoint1 ) * 3.0f;
+    }
+    else
+    {
+      const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+      //X
+      Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+      tangent.x  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+      //Y
+      cVect.x  = point0.y;
+      cVect.y  = controlPoint0.y;
+      cVect.z  = controlPoint1.y;
+      cVect.w  = point1.y;
+      tangent.y  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+      //Z
+      cVect.x  = point0.z;
+      cVect.y  = controlPoint0.z;
+      cVect.z  = controlPoint1.z;
+      cVect.w  = point1.z;
+      tangent.z  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+    }
+
+    tangent.Normalize();
+    done = true;
   }
 
-  tangent.Normalize();
-  return tangent;
+  return done;
 }
 
 Vector3& Path::GetPoint( size_t index )
index 26a1a01..a0d2ba4 100644 (file)
@@ -165,20 +165,32 @@ public:
   void Sample( float t, Vector3& position, Vector3& tangent ) const;
 
   /**
+   * @brief Sample path at a given progress. Calculates position and tangent at that point of the curve
+   *
+   * @param[in]  progress  A floating point value between 0.0 and 1.0.
+   * @param[out] position The interpolated position at that progress.
+   * @param[out] tangent The interpolated tangent at that progress.
+   * @return true if Sample could be calculated
+   */
+  bool SampleAt( float t, Vector3& position, Vector3& tangent ) const;
+
+  /**
    * Sample position at point t.
    *
    * @param[in] progress  A floating point value between 0.0 and 1.0.
    * @param[out] position The interpolated position at that progress.
+   * @return true if sample could be calculated
    */
-  Vector3 SamplePosition( float t ) const;
+  bool SamplePosition( float t, Vector3& position ) const;
 
   /**
    * @brief Sample tangent at point t.
    *
    * @param[in] progress  A floating point value between 0.0 and 1.0.
    * @param[out] tangent The interpolated tangent at that progress.
+   * @return true if sample could be calculated
    */
-  Vector3 SampleTangent( float t ) const;
+  bool SampleTangent( float t, Vector3& tangent ) const;
 
   /**
    * @copydoc Dali::Path::GetPoint
index 02ccfc2..486d2de 100644 (file)
@@ -988,7 +988,9 @@ struct PathPositionFunctor : public AnimatorFunctionBase
 
   Vector3 operator()(float progress, const Vector3& property)
   {
-    return mPath->SamplePosition(progress );
+    Vector3 position(property);
+    static_cast<void>( mPath->SamplePosition(progress, position) );
+    return position;
   }
 
   PathPtr mPath;
@@ -1005,8 +1007,15 @@ struct PathRotationFunctor : public AnimatorFunctionBase
 
   Quaternion operator()(float progress, const Quaternion& property)
   {
-    Vector3 tangent( mPath->SampleTangent(progress) );
-    return Quaternion( mForward, tangent );
+    Vector3 tangent;
+    if( mPath->SampleTangent(progress, tangent) )
+    {
+      return Quaternion( mForward, tangent );
+    }
+    else
+    {
+      return property;
+    }
   }
 
   PathPtr mPath;