3

我正在用 Java 编写植绒算法,但我被困在某个点(使用 Ardor3D 库,在 2D 平面中)。

基本上,我需要找到添加到当前旋转的角度差。如果你只能得到它应该指向北极0度而不是差的方式,不用担心——我有一个方法可以返回角度差,考虑到角度和负角度的环绕。

替代文字

目前,我有以下代码,这显然是行不通的,因为该算法没有参考初始旋转:

  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();

我不太擅长数学问题,所以代码会比公式更有帮助:)

输入

  • 实体当前位置
  • 实体的当前旋转(以度数为单位)

输出

  • 添加或减去当前旋转的度数或弧度
  • ...或度数或弧度表示为极坐标角

如果您能提供帮助,请提前感谢:)

克里斯

4

4 回答 4

2

您可以使用点积来确定当前方向与您要面对的点之间的角度(以弧度为单位)的余弦值。假设进行查看的代理位于原点并面向某个方向,该方向由相对于 Y 轴的角度 θ 给出(即 0 度是“向上”或“向北”)。您想找到该方向与面对点 (x, y) 之间的角度差 θ'。这是由:

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

从 θ 中减去 θ' 将使智能体朝向目标。

如果代理不在原点,只需从要查看的对象中减去代理的位置,即可将其带入上述表格。

于 2010-10-29T16:15:23.553 回答
1

稍微偏离主题,但您可能会发现我们的效果包 (ardor3d-effects) 中的粒子群和漫游代码也很有趣。

它们可以在 ardor svn 中找到,或者在这里:

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

于 2010-11-27T03:50:27.133 回答
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;
    }
}

希望有帮助...

于 2010-10-29T16:34:00.773 回答
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())
于 2010-10-29T18:25:45.373 回答