2016-09-01 136 views
0

我想繪製平滑的*和隨機路徑,我的對象將遵循,我決定去與二次貝塞爾曲線(但我打開其他想法)。繪製具有二次貝塞爾曲線的隨機路徑

我的代碼以隨機但不平滑的方式移動我的對象。

前瞻:https://youtu.be/Eg9PEKuH4zA

我的問題是:我怎麼能做出方向變化更順暢?我應該徹底拋棄Bezier解決方案,還是有辦法擦亮我的代碼以實現我想要的?

*光滑==沒有突然的方向變化

我的代碼:

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

public class Lights : MonoBehaviour { 
    public float paintHeight = -90.0f; 
    public static int NUMBER_OF_LIGHTS = 3; 
    private static int BEZIER_PATH_POINTS = 100; 
    private float GOLDEN_COLOR_RATIO = 0.618033988749895f; 
    private Light[] lights = new Light[NUMBER_OF_LIGHTS]; 

    Vector3 RandomPoint() { 
     float obj_width = gameObject.GetComponent<RectTransform>().rect.width; 
     float screenX = Random.Range(-obj_width/2, obj_width/2); 

     float obj_height = gameObject.GetComponent<RectTransform>().rect.height; 
     float screenY = Random.Range(-obj_height/2, obj_height/2); 

     return new Vector3(screenX, screenY, -paintHeight); 
    } 


    Vector3 QuadraticBezierPoint(Vector3 startPoint, Vector3 endPoint, Vector3 vertexPoint, float t) { 
     /* 
     *   vertex 
     *  /╲ 
     *  / ╲ 
     * /p ╲ 
     * /. . ╲ 
     * /.  · ╲ 
     * /·   · ╲ 
     * start   · end 
     * 
     * 0 < t < 1 
     * 
     * B(t) = (1 - t)^2 * P0 + 2 * (1-t) * t * P1 + t^2 * P2 
     * 
     */ 
     return Mathf.Pow((1 - t), 2) * startPoint + 2 * (1 - t) * t * vertexPoint + Mathf.Pow(t, 2) * endPoint; 
    } 

    Color RandomColor() { 
     float h = Random.Range(0.0f, 1.0f) + GOLDEN_COLOR_RATIO; 
     h %= 1; 
     return Color.HSVToRGB(h, 0.99f, 0.99f); 
    } 

    void Start() { 
     for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
      GameObject light_obj = new GameObject(); 
      Light light = light_obj.AddComponent<Light>(); 
      light.type = LightType.Point; 
      light.range = 10.0f; 
      light.intensity = 3.5f; 
      light.renderMode = LightRenderMode.ForcePixel; 
      light.name = "Light" + i; 
      light.transform.parent = gameObject.transform; 
      lights[i] = light; 
     } 

     StartCoroutine("Move"); 
    } 

    IEnumerator Move() { 
     Dictionary<string, Vector3>[] light_points = new Dictionary<string, Vector3>[NUMBER_OF_LIGHTS]; 
     Dictionary<string, Color>[] light_colors = new Dictionary<string, Color>[NUMBER_OF_LIGHTS]; 
     for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
      light_points[i] = new Dictionary<string, Vector3>(); 
      light_colors[i] = new Dictionary<string, Color>(); 
      //light_points[i]["startPoint"] = RandomPoint(); 
      //light_points[i]["vertexPoint"] = RandomPoint(); 
      light_points[i]["endPoint"] = RandomPoint(); 
      light_colors[i]["nextColor"] = RandomColor(); 
     } 

     while(true) { 
      for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
       light_points[i]["startPoint"] = light_points[i]["endPoint"]; 
       light_points[i]["vertexPoint"] = RandomPoint(); 
       light_points[i]["endPoint"] = RandomPoint(); 

       light_colors[i]["currentColor"] = light_colors[i]["nextColor"]; 
       light_colors[i]["nextColor"] = RandomColor(); 
      } 

      for (int i = 0; i < BEZIER_PATH_POINTS; i++) { 
       float percent = (float)i/BEZIER_PATH_POINTS; 
       for (int j = 0; j < NUMBER_OF_LIGHTS; j++) { 
        lights[j].transform.localPosition = QuadraticBezierPoint(
         light_points[j]["startPoint"], 
         light_points[j]["endPoint"], 
         light_points[j]["vertexPoint"], 
         percent 
        ); 
        lights[j].color = Color.Lerp(light_colors[j]["currentColor"], light_colors[j]["nextColor"], percent); 
       } 
       yield return new WaitForSeconds(0.02f); 
      } 
     } 
    } 
} 
+0

您的視頻並沒有真正的幫助,它是瀰漫的燈光在令人分心的背景上移動,因此無法確定正在追蹤的路徑。通過描述實際的問題開始:單曲線是平滑的,所以是從一個曲線去到下一個不順暢的問題?如果是這樣,解決方案是確保G1或甚至G2連續性,爲更高階曲線更好,像一個三次曲線。在那一點上,使用Catmul-Rom曲線更有意義,因爲那些曲線通過您定義的點(曲線上的每個部分都簡單地轉換爲Bezier形式) –

回答

1

如果你有一個曲線從A與一些中間點到B,你就必須相應地選擇一個C因此B處的角度(A,B,C)不會太小或太大。

此外,您必須以適當的方式選擇中間點,請參閱https://www.particleincell.com/2012/bezier-splines/,所以方向的變化不是太大。

0

你可以去所有的方式使用NURBS或其他一些花,但有可能得到平滑的曲線給你貼什麼的更簡單,等效方式。

您創建的每條曲線在代碼開始,頂點和結束點都有3個點。讓我們稱它們爲S,V和E.另外,讓我們通過時間來看看它們,所以{S0,V0,E0}做出第一條曲線,{S1,V1,E1}做出第二條曲線,等等。

現在您可以確保S1=E0,S2=E1等等。這意味着你的燈光不會隨機跳躍,但當切換貝塞爾曲線時,運動會突然發生。

爲確保運動平穩,請嘗試確保S1 = E0 = 0.5 * (V0+V1)。這在實踐中意味着你隨機生成S0和V0。然後,爲每條新曲線生成一個新的V,並且舊V與新V之間的中點是曲線斷點。

這相當於具有均勻度2 B樣條。

下面是一些示例代碼,可能是說明性的。

// initialize with randomness 
// we need a previous v and a current v for the first iteration 
// So, the first start point will be halfway between these two points 
prev_v = random_point() 
v = random_point() 

while(true) 
{ 
    next_v = random_point() 
    s = 0.5 * (prev_v + v) // s is halfway between prev_v and v 
    e = 0.5 * (v + next_v) // e is halfway between v and next_v 
    yield_movement_bezier(s, v, e) 

    // prep for next iteration 
    prev_v = v 
    v = next_v 
} 
+0

我不認爲這會起作用。 https://ibin.co/31dRdvQTxJDw.jpg – alexandernst

+0

所以,在你的圖中,E0應該在V0和V1的中點。用這種方法,你不會隨機產生任何進一步的E值,只是V值。我會添加一些僞代碼來澄清。 – tfinniga