找到用于旋转给定实体的增量角度,该实体具有位置、初始旋转和“面向”目标点。

发布于 2024-09-29 23:41:55 字数 2589 浏览 4 评论 0原文

我正在用 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();

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

输入

  • 实体的当前位置
  • 当前旋转实体(极向)的度数

输出

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

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

Chris

I'm coding a flocking algorithm in Java but I'm stuck at a certain point (using the Ardor3D libraries, in a 2D plane).

Basically, I need to find the angle difference to add to the current rotation. If you can only get the way it should be pointing with polar coordinates with 0 degs at north and not the difference, not to worry -- I have a method which returns the angle difference taking into account the wraparound on the angle and negative angles.

alt text

At the moment, I have the following code, which clearly wouldn't work since the algorithm has no reference to the initial rotation:

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

Updated code (not working, from first answer):

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

Another modification based on the other answer:

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

I'm not really too good at Maths problems, so code would be helpful rather than formulas :)

Inputs

  • Current position of entity
  • Current rotation of entity (polar-oriented) in degrees

Output

  • Degrees or radians to add or subtract to current rotation
  • ... or degrees or radians expressed as polar-oriented angle

Thanks in advance if you can help :)

Chris

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

花心好男孩 2024-10-06 23:41:55

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

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

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

如果主体不在原点,只需从要查看的对象中减去主体的位置即可将其带入上面的形式。

You can use the dot product to determine the cosine of the angle (in radians) between the current orientation and the point you want to face. Assume the agent doing the viewing is locate at the origin and oriented to face some direction given by the angle θ relative to the Y-Axis (i.e. 0 degrees is "up" or "north"). You want to find the angular difference θ' between that direction and facing a point (x, y). That is given by:

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

Subtracting θ' from θ will orient the agent towards the target.

If the agent is not at the origin, simply subtract the position of the agent from the object to view to bring it into the form above.

孤千羽 2024-10-06 23:41:55

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

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

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

Slightly off topic, but you might find the particle swarm and wander code in our effects package (ardor3d-effects) interesting as well.

They can be found in the ardor svn, or here:

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

猫七 2024-10-06 23:41:55

这是如何找到具有共同原点的两个向量之间的角度的实现。这是根据那里描述的算法组合在一起的:
http://www.wikihow.com/Find-the-Angle-Between -两个向量

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;
    }
}

希望有帮助...

heres an implementation on how to find the angle beetween two vectors with a common origin. this has been hacked together based on the algorithm described there:
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;
    }
}

hope that helps...

带刺的爱情 2024-10-06 23:41:55

如果我正确理解这些函数,这可能会起作用:

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

If I understand these functions correctly, this might just work:

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

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

P.S. Forgot to mention: this rot is intended to be the angle difference. Rotate the entity by this much and it should be pointing toward the target.

EDIT:
Thanks, the code does help (I had misconstrued angleBetween). Let me try again:

Here is the vector from the entity to the point (pardon me if I get the syntax wrong, I don't know java):

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

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

Now we normalize it to get a unit vector pointing toward the point, and take the angle difference:

double rot = rt.getRotation().angleBetween(direction.normalizeLocal())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文