2010-10-29 394 views
3

我正在編碼Java中的植絨算法,但我被困在某個點(使用Ardor3D庫,在一個2D平面)。查找三角形角度用於旋轉給定實體的位置,初始旋轉和目標點'面向'

基本上,我需要找到要添加到當前旋轉的角度差。如果你只能用極座標指向北極0度的位置而不考慮差別,不用擔心 - 我有一種方法可以返回角度差,同時考慮角度和負角度的環繞。

alt text

此刻,我有以下的代碼,這顯然不會因爲算法的工作沒有參考初始旋轉:

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 

    Vector2 pos = new Vector2(); 
    rt.getPosition(pos); 

    double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()); 
    rt.setRotation(rot); 

    pos.addLocal(
    Math.cos((rot - MathUtils.HALF_PI)) * (tpf/10f), 
    Math.sin((rot - MathUtils.HALF_PI)) * (tpf/10f) 
); 
    rt.setPosition(pos); 

    super.updateLogic(); 

更新後的代碼(不工作,從第一個答案):

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 
    //rt.setRotation(rt.getRotation() + ((tpf/(ROT_SPEED/2f)) % 360)); 

    Vector2 avgpos = app.getAvgBoidPos(new Vector2()); 
    Vector2 pos = rt.getPosition(new Vector2()); 
    avgpos.subtractLocal(pos); 

    double angleRads = rt.getRotation() * FastMath.DEG_TO_RAD; 
    double rot = MathUtils.acos((
     (avgpos.getX() * MathUtils.sin(angleRads) 
    ) + 
     (avgpos.getY() * MathUtils.cos(angleRads) 
    ))/((Math.pow(avgpos.getX(), 2) + Math.pow(avgpos.getY(), 2)) * 0.5)); 

    double adegdiff = rot * FastMath.RAD_TO_DEG; 

    rt.setRotation(rt.getRotation() - adegdiff); 
    double newrot = rt.getRotation(); 

    pos.addLocal(
     Math.cos((newrot - MathUtils.HALF_PI)) * (tpf/10f), 
     Math.sin((newrot - MathUtils.HALF_PI)) * (tpf/10f) 
    ); 
    rt.setPosition(pos); 

    super.updateLogic(); 

基於對方的回答另一種修飾:

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 
    //rt.setRotation(rt.getRotation() + ((tpf/(ROT_SPEED/2f)) % 360)); 

    Vector2 avgpos = app.getAvgBoidPos(new Vector2()); 
    Vector2 pos = rt.getPosition(new Vector2()); 
    avgpos.subtractLocal(pos); 

    double rot = pos.angleBetween(
     app.getAvgBoidPos(new Vector2()).normalizeLocal() 
    ) - (rt.getRotation() * MathUtils.DEG_TO_RAD); 

    rt.setRotation(rt.getRotation() - (rot * MathUtils.RAD_TO_DEG)); 
    double newrot = rt.getRotation(); 

    pos.addLocal(
     Math.cos((newrot - MathUtils.HALF_PI)) * (tpf/10f), 
     Math.sin((newrot - MathUtils.HALF_PI)) * (tpf/10f) 
    ); 
    rt.setPosition(pos); 

    super.updateLogic(); 

我不是一個真正的數學問題不太好,所以代碼將是有益的,而不是公式:)

輸入

  • 實體的當前位置
  • 當前實體的旋轉(極性取向)以度

輸出

  • 度或弧度來增加或減少當前旋轉
  • ...或學位或弧度提前表示爲導向的極角

謝謝如果你能幫助:)

克里斯

+0

所以'rt.getPosition'給出了實體的位置和'app.getAvgBOIDPos'給出了目標位置,是這樣嗎?什麼給了實體的方向? – Beta 2010-10-29 15:41:07

+0

這就是rt.getRotation(),它是以面向極座標的度數表示的:) – 2010-10-29 15:42:25

+0

糟糕,忘記說你對應用程序是正確的,getAvgBoidPos()給出了實體向實體移動的平均位置。 – 2010-10-29 15:53:58

回答

2

可以使用點積來確定當前方向與要面對的點之間的角度(弧度)的餘弦。假設進行觀看的代理位於原點並且面向相對於Y軸(即,0度是「上」或「北」)的角度θ給出的某個方向。你想找到該方向和麪對點(x,y)之間的角度差θ'。

θ' = cos-1[(x*sin(θ) + y*cos(θ))/sqrt(x2 + y2)]

減去θ「從θ會朝向目標的代理:即由下式給出。

如果代理不在原點,只需將代理的位置從要查看的對象中減去以將其置於上面的表單中即可。

+0

明白了。我會嘗試實施這個,並回來給你,如果有任何問題:) – 2010-10-29 16:18:09

+0

我實現了它,但它似乎並沒有工作。我認爲位置的x和y元素由於在某處被零除而得到NaN?無論如何,我用新代碼更新了這個問題:) – 2010-10-29 16:44:01

+0

@Chris Dennett:我認爲我爲了自己的利益而努力過於聰明。您將分母乘以1/2。我試圖把它提升到1/2的平方根。對於x和y的某些值,這可能導致商不在[-1,1]的範圍內,這會導致NaN。我更新了我的等式以更好地表明這一點。 – andand 2010-10-29 18:38:51

0

繼承人是如何找到具有共同起源的兩個向量之間的角度的實現。 http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors

public class DeltaDoodle { 

    private double delta(ColumnVector v1,ColumnVector v2) throws Exception{ 
     double sp=scalarProduct(v1,v2); 
     double magV1=magnitude(v1); 
     double magV2=magnitude(v2); 
     return Math.acos(sp/(magV1*magV2)) * (180/Math.PI); 
    } 

    private double scalarProduct(ColumnVector a, ColumnVector b) { 
     return (a.x*b.x) + (a.y*b.y); 
    } 
    private double magnitude(ColumnVector a){ 
     return Math.sqrt((a.x*a.x) + (a.y*a.y)); 
    } 

    public static void main(String[] args) { 
     DeltaDoodle v=new DeltaDoodle(); 
     try { 
      System.out.println("angle: " + v.delta(new ColumnVector(5, 5), new ColumnVector(1,1))); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

public class ColumnVector { 
    public final double x, y; 

    public ColumnVector(double x1, double x2) { 
     this.x = x1; 
     this.y = x2; 
    } 
} 

希望幫助...

0

如果我正確理解這些功能,這可能只是工作:

Vector2 pos = new Vector2(); 
rt.getPosition(pos); 

double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()) - rt.getRotation(); 

基於有描述的算法在這個被黑客攻擊了一起PS忘了提及:這rot旨在是角度差異。通過這麼多的旋轉實體,它應該指向目標。

編輯:
謝謝,代碼沒有幫助(我誤解angleBetween)。讓我再試一次:

下面是從實體點(原諒我,如果我得到的語法錯了,我不知道的Java)的載體:

Vector2 pos = new Vector2(); 
rt.getPosition(pos); 

Vector2 direction = app.getAvgBoidPos(new Vector2()); 
direction.subtractLocal(pos); 

現在我們正常化它來獲得朝向點指向的單位向量,並採取了角的差

double rot = rt.getRotation().angleBetween(direction.normalizeLocal()) 
+0

不工作:/如果有幫助,這裏是Vector2源代碼:http://ardorlabs.trac.cvsdude.com/Ardor3Dv1/browser/trunk/ardor3d-core/src/main/java/com/ardor3d/math/Vector2 .java?rev = 152 – 2010-10-29 18:54:52

1

稍微偏離主題,但你可能會發現粒子羣,並在我們的特效軟件包徜徉代碼(ardor3d效果)也很有趣。

他們可以在熱情SVN發現,這裏還是:

http://ardorlabs.trac.cvsdude.com/Ardor3Dv1/browser/trunk/ardor3d-effects/src/main/java/com/ardor3d/extension/effect/particle/

+0

哦,歡呼雷南瑟! :D – 2010-11-27 19:26:47

+0

順便說一下,這並不完全脫離主題,因爲我想要實現的東西無論如何都是蜂擁而至:)'發現平均位置'元素是其中的一部分,我得到了它的工作。但也有其他元素的問題,這似乎已經在這裏被整理:) – 2010-11-27 19:31:40

+0

唯一的問題是,粒子代碼沒有旋轉和速度,我可以做 - 它只有速度在X ,y和z。但它們之間轉換不應該很難。如果我將速度作爲旋轉和速度的乘積(我已經有公式),那應該沒問題。 – 2010-11-27 19:36:16