在3D中关注对象

时间:2013-10-12 04:26:10

标签: math 3d directx transformation

我在这里遇到了一些问题,我想要一些帮助。我正试图找到一个旋转,允许我让一个物体跟随玩家(始终面对它)。 我首先尝试做十字产品,点和旋转,但这只是无法正常工作。 然后我继续将它分解为两个旋转(偏航和俯仰)和锁定滚动。它现在有效,但仅限于某些方向(我相信四分之一圆,但可能更少)。 这是我目前的代码:

    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

任何帮助?

2 个答案:

答案 0 :(得分:0)

首先,您必须知道定义要面向查看器的对象平面的矢量。让我们说这个向量是'向前'。通常,此向量可以是转换为世界空间的对象空间中的局部z轴向量。

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

axis = CrossProduct(newDir,forward)

和旋转角度:

angle = acos(DotProduct(newDir,forward))

所有向量必须是单一的。

获得角度和轴后,只需计算定义此旋转的四元数。您可以使用以下API函数来执行此操作:RotationAxis或从头开始构建四元数。

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

答案 1 :(得分: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旋转,而不是相对于最后一次旋转。