【问题标题】:C# Lerping from position to positionC# Leping 从一个位置到另一个位置
【发布时间】:2016-01-07 18:58:53
【问题描述】:

我需要制作一个图片框,以便从一个位置到另一个位置(就像你可以团结一致那样)。
我该怎么做,有内置功能吗?
谢谢:)

【问题讨论】:

  • 请展示您为尝试执行此操作所做的工作或一些有助于我们了解您在做什么的代码。
  • @Elipzer ,我不知道该怎么做,例如在统一引擎中,您可以调用 Vector2.Lerp / Vector3.Lerp / Mathf.Lerp。我怎样才能用微软库做到这一点?或者一个想法这样的事情将如何工作
  • 尝试解释您在问题中知道的代码。您可能需要创建自己的类。
  • @Elipzer ,没有我知道的代码,我所知道的是,在统一和 XNA 中,您可以调用 Vector2.Lerp(Vector2 from , Vector2 to , float weight);但我没有使用向量

标签: c# position lerp


【解决方案1】:

Greg Bahm 写了反向 lerp 方程 firstFloat * by + secondFloat * (1 - by),其中 firstFloat 是 secondFloat,secondFloat 是 firstFloat。

其实,正确的lerp方程是:

firstFloat * (1 - by) + secondFloat * by

但是线性插值最快的方法是:

firstFloat + (secondFloat - firstFloat) * by

这是 2 次加法/减法和 1 次乘法,而不是 2 次加法/减法和 2 次乘法。 Vector2 的 Lerp 是正确的。

另外,最快的方法不太精确(谢谢cid):

不精确的方法,由于浮点运算错误,不能保证当 t = 1 时 v = v1。此方法是单调的
当硬件具有本机融合乘加指令时,可以使用这种形式。 https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support

【讨论】:

  • 第二个实现看起来更简单更干净。非常感谢!
  • 我认为第二个实现使它不太容易理解,做了什么。它可能是数学上正确且最小的。考虑到第一次查看代码(或几年后)的新用户,很可能会更快地理解第一个实现。
  • 注意,最快的方法显然也被认为是不太精确的方法:en.wikipedia.org/wiki/…
【解决方案2】:
    public static float CubicInterpolation(float v0, float v1, float v2, float v3, float t) {
        //var v01 = Lerp( v0, v1, t );
        //var v12 = Lerp( v1, v2, t );
        //var v23 = Lerp( v2, v3, t );
        //var v012 = Lerp( v01, v12, t );
        //var v123 = Lerp( v12, v23, t );
        //return Lerp( v012, v123, t );
        var p = (v3 - v2) - (v0 - v1);
        var q = (v0 - v1) - p;
        var r = v2 - v0;
        var s = v1;
        return (p * t * 3) + (q * t * 2) + (r * t) + s;
        //var r = 1f - t;
        //var f0 = r * r * r;
        //var f1 = r * r * t * 3;
        //var f2 = r * t * t * 3;
        //var f3 = t * t * t;
        //return (v0 * f0) + (v1 * f1) + (v2 * f2) + (v3 * f3);
    }
    public static float QuadraticInterpolation(float v0, float v1, float v2, float t) {
        var v01 = Lerp( v0, v1, t );
        var v12 = Lerp( v1, v2, t );
        return Lerp( v01, v12, t );
    }
    public static float Lerp(float v1, float v2, float t) {
        return v1 + ((v2 - v1) * t);
    }


    public static float CosInterpolation(float t) {
        t = (float) -Math.Cos( t * Math.PI ); // [-1, 1]
        return (t + 1) / 2; // [0, 1]
    }
    public static float PerlinSmoothStep(float t) {
        // Ken Perlin's version
        return t * t * t * ((t * ((6 * t) - 15)) + 10);
    }
    public static float SmoothStep(float t) {
        return t * t * (3 - (2 * t));
    }

【讨论】:

    【解决方案3】:

    线性插值 (lerp) 实际上是一个非常容易实现的函数。等式是

    float Lerp(float firstFloat, float secondFloat, float by)
    {
         return firstFloat * (1 - by) + secondFloat * by;
    }
    

    高阶 Lerp 只是包裹低阶 lerp:

    Vector2 Lerp(Vector2 firstVector, Vector2 secondVector, float by)
    {
        float retX = Lerp(firstVector.x, secondVector.x, by);
        float retY = Lerp(firstVector.y, secondVector.y, by);
        return new Vector2(retX, retY);
    }
    

    DirectX SDK 具有 Unity 等各种数学函数,但仅为 Lerp 带来大量开销。您最好只实现自己的。

    【讨论】:

      【解决方案4】:

      试试这个

        float Lerp(float a, float b, float t)
          {
              //return firstFloat * by + secondFloat * (1 - by);
              return (1f - t) * a + t * b;
          }
      
          PointF Lerp(PointF a, PointF b, float t)
          {
              float retX = Lerp(a.X, b.X, t);
              float retY = Lerp(a.Y, b.Y, t);
              return new PointF(retX, retY);
          }
      

      【讨论】:

        猜你喜欢
        • 2014-11-25
        • 2013-08-25
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多