我正在构建一个使用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轴就会发疯。
我正在试图弄清楚我的数学错误以及如何解决它。
感谢。
答案 0 :(得分:1)
Quaternion
用于定义仅轮换,不方向。例如:它定义了如何将任何给定(单位)向量转换为另一个向量,以便将其旋转指定的量。但它没有定义哪个矢量。更多:有一些无限的可能转换量可以实现这一点。
setFromCross
方法允许您通过提供两个任意向量来指定旋转。然后将设置Quaternion
,以便通过围绕轴垂直将其旋转到您提供的矢量,将第一个矢量转换为第二个矢量。
所以,在你的情况下:
setFromCross(tmp.set(up).crs(Vector3.Z).nor(), direction)
这将设置Quaternion
,以便它将向上矢量和Z +向量的叉积旋转到您的方向向量,沿着垂直于这两个向量的轴。在某些情况下,这可能对你有用,但我怀疑这是你真正想要做的。所以,回答你的问题:那可能就是你的数学出错了。
虽然这超出了你的问题的范围,但让我们看看如何实现你想要达到的目标。
首先定义模型未旋转时的方向。例如。哪一侧向上,哪一侧是向前(方向),哪一侧是向右(或向左)。让我们假设在这种情况下,在你的模型中,你的模型是Y +(upRest = new Vector3(0, 1, 0);
),它面向X +(directionRest = new Vector3(1, 0, 0)
)并且它是正确的是Z +(rightRest = new Vector3(0, 0, 1);
)。
现在定义您想要的旋转方向。除了我们可以使用交叉积(垂直)向量的权利之外,您已经拥有了这一点: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();
)
因为静止方向是轴对齐,我们可以通过矩阵的一个属性获取一个漂亮的小捷径。 Matrix4
可以定义为:4个向量的向量。这四个矢量中的第一个指定旋转的X轴,第二个指定旋转的Y轴,第三个矢量指定旋转的Z矢量,第四个矢量指定位置。因此,使用这个单线程将模型设置为我们想要的方向和位置:
arr.transform.set(directionTarget, upTarget, rightTarget, vs[0]);