基于向量和点

时间:2016-10-25 21:13:13

标签: java android libgdx quaternions

我正在构建一个使用3D的程序。

它基本上由一个用户可以旋转和移动的对象(某种立方体)构成,而我可以通过检查服务器上的同一个对象来观察它们对象的视图,箭头指向它们的点。图。

客户端将其位置,方向和向上发送到服务器3个向量。

我试图让我的箭头根据它们的位置和旋转进行渲染。

我正在使用以下代码执行此操作(使用LibGDX进行3D):

Vector3[] vs;
Vector3 tmp = new Vector3();
batch.begin(wm.cam);
for (SocketWrapper s : clientAtt.keySet()) {// for every client
    vs = clientAtt.get(s); // read the 3 vectors: { position, direction, up }

    tmp.set(vs[2].nor());
    vs[1].nor();

    // arr.transform is the transform of the arrow
    arr.transform.set(vs[0], new Quaternion().setFromCross(tmp.crs(Vector3.Z).nor(), vs[1]));

    batch.render(arr);
}

这是arr

的定义
arrow = new ModelBuilder().createArrow(0, 0, 0, 1, 0, 0, 0.1f, 0.1f, 5, GL20.GL_TRIANGLES, new Material(ColorAttribute.createDiffuse(Color.RED)), VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal);
arr = new ModelInstance(arrow);

如果我只围绕Y轴旋转,一切正常,但如果我使用X / Z轴就会发疯。

我正在试图弄清楚我的数学错误以及如何解决它。

感谢。

1 个答案:

答案 0 :(得分:1)

Quaternion用于定义轮换,方向。例如:它定义了如何将任何给定(单位)向量转换为另一个向量,以便将其旋转指定的量。但它没有定义哪个矢量。更多:有一些无限的可能转换量可以实现这一点。

setFromCross方法允许您通过提供两个任意向量来指定旋转。然后将设置Quaternion,以便通过围绕轴垂直将其旋转到您提供的矢量,将第一个矢量转换为第二个矢量。

所以,在你的情况下:

setFromCross(tmp.set(up).crs(Vector3.Z).nor(), direction)

这将设置Quaternion,以便它将向上矢量和Z +向量的叉积旋转到您的方向向量,沿着垂直于这两个向量的轴。在某些情况下,这可能对你有用,但我怀疑这是你真正想要做的。所以,回答你的问题:那可能就是你的数学出错了。

虽然这超出了你的问题的范围,但让我们看看如何实现你想要达到的目标。

  1. 首先定义模型未旋转时的方向。例如。哪一侧向上,哪一侧是向前(方向),哪一侧是向右(或向左)。让我们假设在这种情况下,在你的模型中,你的模型是Y +(upRest = new Vector3(0, 1, 0);),它面向X +(directionRest = new Vector3(1, 0, 0))并且它是正确的是Z +(rightRest = new Vector3(0, 0, 1);)。

  2. 现在定义您想要的旋转方向。除了我们可以使用交叉积(垂直)向量的权利之外,您已经拥有了这一点:upTarget = new Vector3(vs[2]).nor(); directionTarget = new Vector3(vs[1]).nor(); rightTarget = new Vector3().set(upTarget).crs(directionTraget).nor();请注意,您可能需要在交叉积中交换向上和方向目标向量(.set(directionTarget).crs(upTarget).nor();

  3. 因为静止方向是轴对齐,我们可以通过矩阵的一个属性获取一个漂亮的小捷径。 Matrix4可以定义为:4个向量的向量。这四个矢量中的第一个指定旋转的X轴,第二个指定旋转的Y轴,第三个矢量指定旋转的Z矢量,第四个矢量指定位置。因此,使用这个单线程将模型设置为我们想要的方向和位置:

    arr.transform.set(directionTarget, upTarget, rightTarget, vs[0]);