这似乎是一个简单且记录良好的任务。 我有两个表示模型位置的Vector3对象。
我希望指向位于一个Vector3位置的对象,以便它查看另一个Vector3位置。
最初我看了几个来源,比如; http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/
这似乎将该方法记录为找到角度的点积和轴的叉积。
查看Quaternion源代码似乎“setFromCross”为我做了这个。 所以我尝试了以下代码;
Vector3 thisPoint = this.transState.position.cpy();
Vector3 targetPoint = target.transState.position.cpy();
targetPoint.nor();
thisPoint.nor();
Quaternion result = new Quaternion();
result.setFromCross(targetPoint,thisPoint);
这似乎很简单但没有用 - 显然指出了错误的方法。 然后我尝试手动实现它;
float theirDotProduct = thisPoint.dot(targetPoint);
float angle = (float) Math.acos(theirDotProduct);
Vector3 theirCrossProduct = thisPoint.crs(targetPoint);
Vector3 axis = theirCrossProduct.nor();
//now make a Quaternion from it and return
Quaternion result = new Quaternion();
result.setFromAxisRad(axis, angle);
也没有工作,再次,明确指出错误的方式(并没有90度关闭或固定数量的任何东西,方向和向量之间的关系似乎是错误的)
作为参考我正在使用一个系统,我的模型将它们的位置和旋转存储为vector3s和Quaterions - 为了动画,我只在最后一步转换为Matrix。 用于获取Quaterion并设置模型旋转的确切代码是;
/** lookat the target models vector3 location (currently doesn't work) **/
public void lookAt(AnimatableModelInstance target){
Quaternion angle = getAngleTo(target);
setToRotation(angle);
}
/*** Set the rotation. If doing a more complex change make a PosRotScale and call setTransform **/
public void setToRotation(Quaternion angle) {
transState.rotation.set(angle);
sycnTransform();
}
public void sycnTransform() {
super.transform.set(transState.position, transState.rotation, transState.scale);
}
这似乎对我正在做的所有其他旋转动画都很好,所以我认为错误不在那个区域。
我猜它是我在这里缺少的一些基本步骤或概念。
谢谢, -Thomas
答案 0 :(得分:4)
两个位置之间没有轴/角度。计算两个向量的旋转只有在它们具有相同的位置(原点)时才有用。
请记住,向量不代表某个位置,而是如何从原点到达特定位置(尽管在您的情况下,它实际上可能是相同的,但它在数学上是非常不同的)。您可能已经尝试过使用它,因为您正在规范化向量(在代码中实际上删除了一些重要信息)。
计算位置之间的角度可以获得这些位置相对于原点(位置0,0,0)之间的旋转。换句话说:它会让你旋转thisPoint
向量应该旋转大约0,0,0 以匹配方向(不是长度<{1}}的{/ em>)。注意使用 direction 和 length ,这是另一种说法相同的方式。例如。向量x:5,y:0,z:0的方向为x:1,y:0,z:0,长度为5.
在您的情况下,您需要targetPoint
相对于targetPoint
的向量(尤其是方向,但您不需要长度)。或者换句话说:如果从thisPoint
开始,您应该去哪个方向thisPoint
。这可以通过减去矢量然后归一化结果来容易地计算。需要标准化才能删除长度(将其设置为1),因此我们只保留方向。
targetPoint
现在我们有了你希望模型看到的方向。要计算旋转,我们首先需要知道它在未旋转时的位置。这显然取决于您的模型以及如何建模。假设它的基矢量(未旋转的方向)是Vector3 direction = new Vector3();
direction.set(targetPoint).sub(thisPoint).nor();
,那么你可以使用:
Vector3.X
答案 1 :(得分:3)
我不熟悉libgdx。我的回答没有帮助或明显错误,也许我可以抓住这个peer pressure徽章。
似乎对计算出的角度存在误解。您说您正在存储对象的位置。然后,您正在计算点积
float theirDotProduct = thisPoint.dot(targetPoint);
但是,您从此点积计算的角度与将一个对象沿另一个方向对齐所需的角度无关。您在那里计算的角度基本上是从原点开始并通过对象位置的行之间的角度(也显示在您链接到的站点上的图像中)。
我假设对象的默认方向,旋转角度为零,以及对象“沿x轴指向”的位置。然后,为了对齐这样的对象使其“指向另一个对象的方向”,您必须按如下方式设置该对象的方向:
您必须计算对象之间的差异 - 就像在对象之间绘制的线条一样。然后,您可以计算此线与x轴之间的角度。
这是旋转对象A使其指向对象B所需的角度。
旋转的轴是通过采用叉积来计算的,但不是在对象的位置之间,而是在x轴和对象位置的差异。
代码涉及对libgdx用法的一些猜测,因此可能大致如下:
Vector3 thisPoint = ...;
Vector3 targetPoint = ...;
Vector3 difference = targetPoint.sub(thisPoint);
if (difference.len() < someSmallEpsilon)
{
// Objects are at the same location - can't
// sensibly compute a direction to look at
return;
}
Vector3 direction = difference.nor()
Vector3 xAxis = new Vector3(1,0,0);
float dotProduct = xAxis.dot(direction);
float angle = (float) Math.acos(dotProduct);
if (angle < someSmallEpsilon)
{
// Angle is already right. Nothing to do
return;
}
Vector3 axis = xAxis.crs(direction).nor();
Quaternion result = new Quaternion();
result.setFromAxisRad(axis, angle);
(不要把我钉在标志上 - 可能是角度(或轴)可能被否定 - 但这应该是基本的方法)