うちのいぬ Tech Blog

Tech Blog of Uchinoinu/My dog

ベクトルの線形補間について

全然わからないので、まずは言葉の意味から

補間とは

wikipedia引用

内挿(ないそう、英: interpolation、補間とも言う)とは、ある既知の数値データ列を基にして、そのデータ列の各区間の範囲内を埋める数値を求めること、またはそのような関数を与えること。またその手法を内挿法(補間法)という。内挿するためには、各区間の範囲内で成り立つと期待される関数と境界での振舞い(境界条件)を決めることが必要である。

分かるようなわからないような。

内挿やinterpolationの方が意味が分かるきもします。

Unityでは(以下引用)

まずは二次元から 2D

Vector2.Lerp

説明

a と b by t ベクトルの間で線形補間します。

t は [0...1] の間で制限されます。

When t = 0 returns a. When t = 1 return b. t = 0.5 のときは a と b の平均(ちょうど真ん中)を返します。

使い方

C Sharp

public static Vector2 Lerp(Vector2 a, Vector2 b, float t);

JavaScript

public static function Lerp(a: Vector2, b: Vector2, t: float): Vector2;

3Dでは

Vector3.Lerp

説明

直線上にある 2 つのベクトル間を補間します

t で a と b の間を補間します。t は、0-1 の範囲に固定されています。これは、直線状にあるポイント間(両端)で割合に対しての位置を取得するのに使用します(例えば徐々に目的地へ移動していくときに使用します)。

t = 0 のときは a を返します。 t = 1 のときは b を返します。 t = 0.5 のときは a と b の平均(ちょうど真ん中)を返します。

使い方

C Sharp

public static Vector3 Lerp(Vector3 a, Vector3 b, float t);
using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public Transform startMarker;
    public Transform endMarker;
    public float speed = 1.0F;
    private float startTime;
    private float journeyLength;
    void Start() {
        startTime = Time.time;
        journeyLength = Vector3.Distance(startMarker.position, endMarker.position);
    }
    void Update() {
        float distCovered = (Time.time - startTime) * speed;
        float fracJourney = distCovered / journeyLength;
        transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fracJourney);
    }
}

JavaScript

public static function Lerp(a: Vector3, b: Vector3, t: float): Vector3;
   // Transforms to act as start and end markers for the journey.
    var startMarker: Transform;
    var endMarker: Transform;
    
    // Movement speed in units/sec.
    var speed = 1.0;
    
    // Time when the movement started.
    private var startTime: float;
    
    // Total distance between the markers.
    private var journeyLength: float;    
    
    function Start() {
        // Keep a note of the time the movement started.
        startTime = Time.time;
        
        // Calculate the journey length.
        journeyLength = Vector3.Distance(startMarker.position, endMarker.position);
    }
    
    // Follows the target position like with a spring
    function Update () {
        // Distance moved = time * speed.
        var distCovered = (Time.time - startTime) * speed;
        
        // Fraction of journey completed = current distance divided by total distance.
        var fracJourney = distCovered / journeyLength;
        
        // Set our position as a fraction of the distance between the markers.
        transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fracJourney);
    }

lerp

Three.jsを思いっきり参考にしました。

基本的に(二点間)

  • 書き方1
function lerp (start, end, alpha){
  return (1 - alpha) * start + alpha * end
}

2Dの場合

  • 書き方1
function lerp ( v, alpha ) {
  this.x += ( v.x - this.x ) * alpha;
  this.y += ( v.y - this.y ) * alpha;
  return this;
}
  • 書き方2
function lerpVectors( v1, v2, alpha ) {
  return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
}

function add( v ) {
  this.x += v.x;
  this.y += v.y;

  return this;
}

function subVectors( a, b ) {
  this.x = a.x - b.x;
  this.y = a.y - b.y;
  return this;
}

function multiplyScalar( scalar ) {
  if ( isFinite( scalar ) ) {
    this.x *= scalar;
    this.y *= scalar;
  } else {
    this.x = 0;
    this.y = 0;
  }
  return this;
}

3Dの場合

  • 書き方1
function lerp( v, alpha ) {
  this.x += ( v.x - this.x ) * alpha;
  this.y += ( v.y - this.y ) * alpha;
  this.z += ( v.z - this.z ) * alpha;
  return this;
}
  • 書き方2
function lerpVectors( v1, v2, alpha ) {
  return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
}

function add( v ) {
  this.x += v.x;
  this.y += v.y;
  this.z += v.z;

  return this;
}

function subVectors( a, b ) {
  this.x = a.x - b.x;
  this.y = a.y - b.y;
  this.z = a.z - b.z;
  return this;
}

function multiplyScalar( scalar ) {
  if ( isFinite( scalar ) ) {
    this.x *= scalar;
    this.y *= scalar;
    this.z *= scalar;
  } else {
    this.x = 0;
    this.y = 0;
    this.z = 0;
  }
  return this;
}

こんな感じなのだろうか?