0

我在这里有点问题,我需要一些帮助。我正在尝试找到一种旋转方式,使我可以使物体跟随玩家(始终面对它)。我第一次尝试做叉积,点和旋转,但这不能正常工作。然后我开始将它分解为两个旋转(偏航和俯仰)和锁定滚动。它现在可以工作,但仅适用于某些方向(我相信四分之一圈,但可能更少)。这是我当前的代码:

    XMVECTOR newDir = Vec3DtoDX((Player->Position - InternalEntity->Position).getNormalized());
    XMVECTOR orig = XMVectorSet(0,0,1,0);

    XMVECTOR xNewDir,xOrigDir,yNewDir,yOrigDir;
    xOrigDir = XMVectorSet(0,1,0,0); // (y,z)
    yOrigDir = XMVectorSet(0,1,0,0); // (x,z)

    xNewDir = XMVectorSet(newDir.m128_f32[1],newDir.m128_f32[2],0,0);
    yNewDir = XMVectorSet(newDir.m128_f32[0],newDir.m128_f32[2],0,0);

    float xAngle = XMVector2AngleBetweenVectors(xNewDir,xOrigDir).m128_f32[0];
    float yAngle = XMVector2AngleBetweenVectors(yNewDir,yOrigDir).m128_f32[0];

    XMVECTOR rotDX = XMQuaternionRotationRollPitchYaw(xAngle,yAngle,0);
    PxQuat rot = VecDXto4D<PxQuat>(rotDX);

这里工作正常,如果我面对靠近 Z 轴的物体 http://imgur.com/oNNNRXo

如果我移动更多,它会变成这样:http: //imgur.com/xFIEzdg

任何帮助将不胜感激。

编辑:我已经尝试从十字创建四元数,从点的 acos 创建角度。事实上,这是我的第一次。问题是它不能正常工作。这是我的做法:

    PxVec3 newDir = (Player->Position - InternalEntity->Position).getNormalized();

    PxVec3 orig(0,0,1);

    PxVec3 axis = newDir.cross(orig);

    float angle = XMVector3AngleBetweenVectors(Vec3DtoDX(newDir),Vec3DtoDX(orig)).m128_f32[0];

    PxQuat rot(angle,axis);

其中 XMVector3AngleBetweenVectors 是:

  XMVECTOR L1 = XMVector3ReciprocalLength(V1);
  XMVECTOR L2 = XMVector3ReciprocalLength(V2);

  XMVECTOR Dot = XMVector3Dot(V1, V2);

  L1 = XMVectorMultiply(L1, L2);

  XMVECTOR CosAngle = XMVectorMultiply(Dot, L1);
  CosAngle = XMVectorClamp(CosAngle, g_XMNegativeOne.v, g_XMOne.v);

  return XMVectorACos(CosAngle);

这将导致以下屏幕: http: //imgur.com/vlMPAwG 和:http: //imgur.com/PEz1aMc

有什么帮助吗?

4

2 回答 2

0

首先,您必须知道定义要面向观察者的对象平面的矢量。假设这个向量是“向前的”。通常,该向量可以是转换为世界空间的对象空间中的局部 z 轴向量。

一旦你有了这个向量,你必须找到旋转轴:

轴 = 交叉产品(新目录,前向)

和旋转角度:

角度 = acos(DotProduct(newDir, forward))

其中所有向量必须是单一的。

一旦你有了角度和轴,只需计算定义这个旋转的四元数。您可以使用 API 函数来做到这一点,例如:RotationAxis 或从头开始构建四元数。

最后,一旦你有了四元数,只需使用它旋转你的对象。

于 2013-10-12T08:26:10.713 回答
0

好的,经过很多麻烦,这是一个工作代码:

// Using PxExtendedVec3 to use double
// For ground enemies, just flatten the positions across the Up vector ( set y to 0  in this case )
PxExtendedVec3 newDir = Vec3Dto3D<PxExtendedVec3>(Vec3Dto3D<PxExtendedVec3>(Player->Position) - Vec3Dto3D<PxExtendedVec3>(InternalEntity->Position));
newDir.y = 0;
newDir.normalize();
PxExtendedVec3 orig(0,0,1);
PxExtendedVec3 axis = newDir.cross(orig);

double angle = -asin(_Core::Clamp<double>(axis.magnitude(),-1.0,1.0));
axis.normalize();
// Compensate the [-pi/2,pi/2] range of asin
if(newDir.dot(Vec3Dto3D<PxVec3>(orig)) < 0.0)
    angle = XM_PIDIV2 - angle + XM_PIDIV2;//angle += XM_PI/2.0;

PxQuat rot(angle,Vec3Dto3D<PxVec3>(axis));

其中 PxExtendedVec3 是双精度向量,XM_PIDIV2 是 pi / 2:希望这对某人有所帮助,我已经使用了很长时间。

编辑:一点评论。在这种情况下,我将 Y 设置为 0,因为这会删除一些不需要的滚动,但考虑到该行是可选的,因此如果您愿意,可以使用它。此外,这给出了 ABSOLUTE 旋转,而不是相对于上一次旋转。

于 2013-10-23T18:30:42.967 回答